From 9cb98d05cfddfebc628e05908e444246f438ee08 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 24 Aug 2010 08:53:50 +0000 Subject: [PATCH] Bug 316307: [C++0x] Semantics for lamda expressions. --- .../core/parser/tests/ast2/AST2CPPTests.java | 2 +- .../tests/IndexCPPBindingResolutionTest.java | 4 - .../dom/ast/cpp/ICPPASTLambdaExpression.java | 17 +- .../dom/parser/cpp/CPPASTConversionName.java | 35 +- .../cpp/CPPASTFunctionCallExpression.java | 8 +- .../dom/parser/cpp/CPPASTImplicitName.java | 9 +- .../parser/cpp/CPPASTLambdaExpression.java | 58 ++- .../core/dom/parser/cpp/CPPClosureType.java | 400 ++++++++++++++++++ .../dom/parser/cpp/CPPImplicitFunction.java | 16 +- .../cpp/CPPLambdaExpressionParameter.java | 149 +++++++ .../parser/cpp/semantics/CPPSemantics.java | 8 +- .../dom/parser/cpp/semantics/CPPVisitor.java | 153 +++---- .../dom/parser/cpp/semantics/Conversions.java | 41 +- .../parser/cpp/semantics/SemanticUtil.java | 17 +- .../core/pdom/dom/cpp/PDOMCPPLinkage.java | 6 +- .../core/pdom/indexer/IndexerASTVisitor.java | 52 ++- .../callhierarchy/CppCallHierarchyTest.java | 37 ++ .../ui/editor/SemanticHighlightings.java | 28 +- .../cdt/internal/ui/viewsupport/IndexUI.java | 3 + 19 files changed, 889 insertions(+), 154 deletions(-) create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java create mode 100644 core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPLambdaExpressionParameter.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index c4986dcb3e7..475c8aa5b3e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -8856,7 +8856,7 @@ public class AST2CPPTests extends AST2BaseTest { // return abs(a) < abs(b); // }); // } - public void _testLambdaExpression_316307b() throws Exception { + public void testLambdaExpression_316307b() throws Exception { String code= getAboveComment(); parseAndCheckBindings(code); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java index 40cff12b865..066846e11f5 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPBindingResolutionTest.java @@ -869,7 +869,6 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti // foo/*i*/(23489); // IASTLiteralExpression // foo/*j*/(sizeof(C));/*9*/ // IASTTypeIdExpression // foo/*k*/(*cp);/*10*/ // IASTUnaryExpression - // foo/*l*/(delete cp);/*11*/ // ICPPASTDeleteExpression // foo/*m*/(new C());/*12*/ // ICPPASTNewExpression // // ?? foo/*n*/(); // ICPPASTSimpleTypeConstructorExpression // // ?? foo/*o*/(); // ICPPASTTypenameExprssion @@ -916,9 +915,6 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti IBinding b10 = getBindingFromASTName("foo/*k*/", 3); IBinding b10a = getBindingFromASTName("cp);/*10*/", 2); - IBinding b11 = getBindingFromASTName("foo/*l*/", 3); - IBinding b11a = getBindingFromASTName("cp);/*11*/", 2); - IBinding b12 = getBindingFromASTName("foo/*m*/", 3); IBinding b12a = getBindingFromASTName("C());/*12*/", 1); // IBinding b13 = getBindingFromASTName(ast, "foo/*n*/", 3); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLambdaExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLambdaExpression.java index 41ecd0f3e98..78608a1f211 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLambdaExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTLambdaExpression.java @@ -13,6 +13,8 @@ package org.eclipse.cdt.core.dom.ast.cpp; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTImplicitName; +import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner; /** * Lambda expression, introduced in C++0x. @@ -21,7 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression; * @noextend This interface is not intended to be extended by clients. * @noimplement This interface is not intended to be implemented by clients. */ -public interface ICPPASTLambdaExpression extends IASTExpression { +public interface ICPPASTLambdaExpression extends IASTExpression, IASTImplicitNameOwner { ASTNodeProperty CAPTURE = new ASTNodeProperty("ICPPASTLambdaExpression - CAPTURE [ICPPASTCapture]"); //$NON-NLS-1$ ASTNodeProperty DECLARATOR = new ASTNodeProperty("ICPPASTLambdaExpression - DECLARATOR [ICPPASTFunctionDeclarator]"); //$NON-NLS-1$ ASTNodeProperty BODY = new ASTNodeProperty("ICPPASTLambdaExpression - BODY [IASTCompoundStatement]"); //$NON-NLS-1$ @@ -40,13 +42,24 @@ public interface ICPPASTLambdaExpression extends IASTExpression { * Returns the array of captures for this lambda expression. */ ICPPASTCapture[] getCaptures(); - + + /** + * Returns an implicit name that represents the closure type. + */ + IASTImplicitName getClosureTypeName(); + /** * Returns the lambda declarator for this lambda expression, or null * in case it was not specified. */ ICPPASTFunctionDeclarator getDeclarator(); + /** + * Returns an implicit name that represents the implicit function call operator of + * the closure. + */ + IASTImplicitName getFunctionCallOperatorName(); + /** * Returns the compound statement of this lambda expression. Can be null * when creating AST for content assist. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java index 4090744e8e5..06c87d02aa1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTConversionName.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,6 +14,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IType; @@ -91,25 +92,31 @@ public class CPPASTConversionName extends CPPASTNameBase implements ICPPASTConve public char[] toCharArray() { if (fName == null) { - StringBuilder buf= new StringBuilder(); - buf.append(Keywords.cOPERATOR); - buf.append(' '); + IType t= null; if (typeId != null) { - IType t= CPPVisitor.createType(typeId); - if (t != null) { - buf.append(ASTTypeUtil.getType(t, true)); - } else { - buf.append(typeId.getRawSignature()); - WHITESPACE_SEQ.matcher(buf).replaceAll(" "); //$NON-NLS-1$ - } + t= CPPVisitor.createType(typeId); } - final int len= buf.length(); - fName= new char[len]; - buf.getChars(0, len, fName, 0); + fName= createName(t, typeId); } return fName; } + public static char[] createName(IType t, IASTNode typeId) { + StringBuilder buf= new StringBuilder(); + buf.append(Keywords.cOPERATOR); + buf.append(' '); + if (t != null) { + buf.append(ASTTypeUtil.getType(t, true)); + } else { + buf.append(typeId.getRawSignature()); + WHITESPACE_SEQ.matcher(buf).replaceAll(" "); //$NON-NLS-1$ + } + final int len= buf.length(); + char[] name= new char[len]; + buf.getChars(0, len, name, 0); + return name; + } + public char[] getSimpleID() { return toCharArray(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java index 7b6bc969e8d..0288025321d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionCallExpression.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; @@ -109,8 +110,11 @@ public class CPPASTFunctionCallExpression extends ASTNode implements public IASTImplicitName[] getImplicitNames() { if (implicitNames == null) { ICPPFunction overload = getOperator(); - if (overload == null || overload instanceof CPPImplicitFunction) - return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; + if (overload == null || overload instanceof CPPImplicitFunction) { + if (!(overload instanceof ICPPMethod) || ((ICPPMethod) overload).isImplicit()) { + return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; + } + } // create separate implicit names for the two brackets CPPASTImplicitName n1 = new CPPASTImplicitName(OverloadableOperator.PAREN, this); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java index bee62bfccb0..c3b5d23df4e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTImplicitName.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode; public class CPPASTImplicitName extends CPPASTName implements IASTImplicitName { private boolean alternate; private boolean isOperator; + private boolean isDefinition= false; public CPPASTImplicitName(char[] name, IASTNode parent) { super(name); @@ -74,12 +75,16 @@ public class CPPASTImplicitName extends CPPASTName implements IASTImplicitName { @Override public boolean isDefinition() { - return false; + return isDefinition; } @Override public boolean isReference() { - return true; + return !isDefinition; + } + + public void setIsDefinition(boolean val) { + isDefinition= val; } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java index 72832388ab4..7b26865abff 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTLambdaExpression.java @@ -13,10 +13,11 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTExpression; -import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IASTImplicitName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; @@ -29,7 +30,12 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr private CaptureDefault fCaptureDefault; private ICPPASTCapture[] fCaptures; private ICPPASTFunctionDeclarator fDeclarator; + private IASTCompoundStatement fBody; + + private CPPClosureType fClosureType; + private IASTImplicitName fClosureTypeName; + private IASTImplicitName fImplicitFunctionCallName; public CPPASTLambdaExpression() { fCaptureDefault= CaptureDefault.UNSPECIFIED; @@ -59,6 +65,41 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr return result; } + public IASTImplicitName[] getImplicitNames() { + return new IASTImplicitName[] {getFunctionCallOperatorName()}; + } + + public IASTImplicitName getClosureTypeName() { + if (fClosureTypeName == null) { + final CPPClosureType closureType = getExpressionType(); + CPPASTImplicitName name = new CPPASTImplicitName(closureType.getNameCharArray(), this); + name.setBinding(closureType); + name.setIsDefinition(true); + + name.setOffsetAndLength(getOffset(), 1); + fClosureTypeName= name; + } + return fClosureTypeName; + } + + public IASTImplicitName getFunctionCallOperatorName() { + if (fImplicitFunctionCallName == null) { + final CPPClosureType closureType = getExpressionType(); + ICPPFunction callOperator= closureType.getFunctionCallOperator(); + + CPPASTImplicitName name = new CPPASTImplicitName(closureType.getNameCharArray(), this); + name.setBinding(callOperator); + name.setIsDefinition(true); + + if (fBody instanceof ASTNode) { + ASTNode bodyNode= (ASTNode) fBody; + name.setOffsetAndLength(bodyNode.getOffset(), 1); + } + fImplicitFunctionCallName= name; + } + return fImplicitFunctionCallName; + } + @Override public boolean accept(ASTVisitor visitor) { if (visitor.shouldVisitExpressions) { @@ -69,6 +110,9 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr } } + if (visitor.shouldVisitImplicitNames && !getClosureTypeName().accept(visitor)) + return false; + if (fCaptures != null) { for (ICPPASTCapture cap : fCaptures) { if (cap != null && !cap.accept(visitor)) @@ -77,6 +121,10 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr } if (fDeclarator != null && !fDeclarator.accept(visitor)) return false; + + if (visitor.shouldVisitImplicitNames && !getFunctionCallOperatorName().accept(visitor)) + return false; + if (fBody != null && !fBody.accept(visitor)) return false; @@ -133,9 +181,11 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr fDeclarator= dtor; } - public IType getExpressionType() { - // mstodo type for lambda expressions - return null; + public CPPClosureType getExpressionType() { + if (fClosureType == null) + fClosureType= new CPPClosureType(this); + + return fClosureType; } public boolean isLValue() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java new file mode 100644 index 00000000000..b71af457f09 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClosureType.java @@ -0,0 +1,400 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.core.dom.ILinkage; +import org.eclipse.cdt.core.dom.IName; +import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; +import org.eclipse.cdt.core.dom.ast.EScopeKind; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTypeId; +import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IField; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression.CaptureDefault; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.core.index.IIndexBinding; +import org.eclipse.cdt.core.index.IIndexFileSet; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.Linkage; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.core.runtime.PlatformObject; + +/** + * Binding for a class type. + */ +public class CPPClosureType extends PlatformObject implements ICPPClassType, ICPPInternalBinding { + private static final CPPBasicType NO_RETURN_TYPE = new CPPBasicType(Kind.eUnspecified, 0); + + private final ICPPASTLambdaExpression fLambdaExpression; + private ICPPMethod[] fMethods; + private ClassScope fScope; + + public CPPClosureType(ICPPASTLambdaExpression lambdaExpr) { + fLambdaExpression= lambdaExpr; + } + + private ICPPMethod[] createMethods() { + boolean needConversionOperator= + fLambdaExpression.getCaptureDefault() == CaptureDefault.UNSPECIFIED && + fLambdaExpression.getCaptures().length == 0; + + final ICPPClassScope scope= getCompositeScope(); + ICPPMethod[] result= new ICPPMethod[needConversionOperator ? 6 : 5]; + + // Deleted default constructor: A() + CPPImplicitConstructor ctor= new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY); + ctor.setDeleted(true); + result[0]= ctor; + + // Copy constructor: A(const A &) + IType pType = new CPPReferenceType(SemanticUtil.addQualifiers(this, true, false), false); + ICPPParameter[] ps = new ICPPParameter[] { new CPPParameter(pType, 0) }; + ctor = new CPPImplicitConstructor(scope, CharArrayUtils.EMPTY, ps); + result[1]= ctor; + + // Deleted copy assignment operator: A& operator = (const A &) + IType refType = new CPPReferenceType(this, false); + ICPPFunctionType ft= CPPVisitor.createImplicitFunctionType(refType, ps, false, false); + ICPPMethod m = new CPPImplicitMethod(scope, OverloadableOperator.ASSIGN.toCharArray(), ft, ps); + result[2]= m; + + // Destructor: ~A() + ft= CPPVisitor.createImplicitFunctionType(NO_RETURN_TYPE, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY, false, false); + m = new CPPImplicitMethod(scope, new char[] {'~'}, ft, ICPPParameter.EMPTY_CPPPARAMETER_ARRAY); + result[3]= m; + + // Function call operator + final IType returnType= getReturnType(); + final IType[] parameterTypes= getParameterTypes(); + ft= new CPPFunctionType(returnType, parameterTypes, isMutable(), false, false); + + ICPPParameter[] params = new ICPPParameter[parameterTypes.length]; + for (int i = 0; i < params.length; i++) { + params[i]= new CPPParameter(parameterTypes[i], 0); + } + m= new CPPImplicitMethod(scope, OverloadableOperator.PAREN.toCharArray(), ft, params) { + @Override + public boolean isImplicit() {return false;} + }; + result[4]= m; + + // Conversion operator + if (needConversionOperator) { + final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes); + ft= new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false); + m= new CPPImplicitMethod(scope, CPPASTConversionName.createName(conversionTarget, null), ft, params); + result[5]= m; + } + return result; + } + + public ICPPMethod getFunctionCallOperator() { + return getMethods()[4]; + } + + private boolean isMutable() { + ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator(); + return lambdaDtor != null && lambdaDtor.isMutable(); + } + + private IType getReturnType() { + ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator(); + if (lambdaDtor != null) { + IASTTypeId trailingReturnType = lambdaDtor.getTrailingReturnType(); + if (trailingReturnType != null) { + IType type= CPPVisitor.createType(trailingReturnType); + if (type != null) + return type; + return CPPSemantics.VOID_TYPE; + } + } + IASTCompoundStatement body = fLambdaExpression.getBody(); + if (body != null) { + IASTStatement[] stmts = body.getStatements(); + if (stmts.length > 0) { + // Gnu extension allows to deduce return type in complex compound statements + IASTStatement stmt= stmts[stmts.length-1]; + if (stmt instanceof IASTReturnStatement) { + IASTReturnStatement rtstmt= (IASTReturnStatement) stmt; + IASTExpression expr= rtstmt.getReturnValue(); + if (expr != null) { + IType type= expr.getExpressionType(); + type= Conversions.lvalue_to_rvalue(type); + type= Conversions.array_to_pointer(type); + type= Conversions.function_to_pointer(type); + if (type != null) { + return type; + } + } + } + } + } + return CPPSemantics.VOID_TYPE; + } + + private IType[] getParameterTypes() { + ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator(); + if (lambdaDtor != null) { + return CPPVisitor.createParameterTypes(lambdaDtor); + } + return IType.EMPTY_TYPE_ARRAY; + } + + public final String getName() { + return ""; //$NON-NLS-1$ + } + + public char[] getNameCharArray() { + return CharArrayUtils.EMPTY; + } + + public IScope getScope() { + return CPPVisitor.getContainingScope(fLambdaExpression); + } + + public ICPPClassScope getCompositeScope() { + if (fScope == null) { + fScope= new ClassScope(); + } + return fScope; + } + + public int getKey() { + return k_class; + } + + public String[] getQualifiedName() { + return CPPVisitor.getQualifiedName(this); + } + + public char[][] getQualifiedNameCharArray() { + return CPPVisitor.getQualifiedNameCharArray(this); + } + + public boolean isGloballyQualified() { + return getOwner() == null; + } + + public ILinkage getLinkage() { + return Linkage.CPP_LINKAGE; + } + + public boolean isSameType(IType type) { + if (type == this) + return true; + if (type instanceof ITypedef || type instanceof IIndexBinding) + return type.isSameType(this); + return false; + } + + public ICPPBase[] getBases() { + return ICPPBase.EMPTY_BASE_ARRAY; + } + + public ICPPField[] getFields() { + return ICPPField.EMPTY_CPPFIELD_ARRAY; + } + + public ICPPField[] getDeclaredFields() { + return ICPPField.EMPTY_CPPFIELD_ARRAY; + } + + public ICPPMethod[] getMethods() { + if (fMethods == null) { + fMethods= createMethods(); + } + return fMethods; + } + + public ICPPMethod[] getAllDeclaredMethods() { + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; + } + + public ICPPMethod[] getDeclaredMethods() { + return ICPPMethod.EMPTY_CPPMETHOD_ARRAY; + } + + public ICPPConstructor[] getConstructors() { + ICPPMethod[] methods= getMethods(); + int i= 0; + for (; i < methods.length; i++) { + if (!(methods[i] instanceof ICPPConstructor)) { + break; + } + } + ICPPConstructor[] result= new ICPPConstructor[i]; + System.arraycopy(methods, 0, result, 0, i); + return result; + } + + public IBinding[] getFriends() { + return IBinding.EMPTY_BINDING_ARRAY; + } + + public ICPPClassType[] getNestedClasses() { + return ICPPClassType.EMPTY_CLASS_ARRAY; + } + + public IField findField(String name) { + return null; + } + + @Override + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + } + return null; + } + + /** + * For debugging purposes, only. + */ + @Override + public String toString() { + char[] name= ASTTypeUtil.createNameForAnonymous(this); + if (name != null) + return new String(name); + return null; + } + + public IBinding getOwner() { + return CPPVisitor.findDeclarationOwner(fLambdaExpression, true); + } + + public boolean isAnonymous() { + return false; + } + + public IASTNode getDefinition() { + return fLambdaExpression; + } + + public IASTNode[] getDeclarations() { + return IASTNode.EMPTY_NODE_ARRAY; + } + + public void addDefinition(IASTNode node) { + } + + public void addDeclaration(IASTNode node) { + } + + + private final class ClassScope implements ICPPClassScope { + public EScopeKind getKind() { + return EScopeKind.eClassType; + } + + public IName getScopeName() { + return null; + } + + public IScope getParent() { + return getScope(); + } + + private IBinding getBinding(char[] name) { + for (ICPPMethod m : getMethods()) { + if (!(m instanceof ICPPConstructor) && CharArrayUtils.equals(name, m.getNameCharArray())) { + return m; + } + } + return null; + } + + private IBinding[] getBindings(char[] name) { + IBinding m= getBinding(name); + if (m != null) { + return new IBinding[] {m}; + } + return IBinding.EMPTY_BINDING_ARRAY; + } + + private IBinding[] getPrefixBindings(char[] name) { + List result= new ArrayList(); + for (ICPPMethod m : getMethods()) { + if (!(m instanceof ICPPConstructor)) { + if (CharArrayUtils.equals(name, 0, name.length, m.getNameCharArray(), true)) { + result.add(m); + } + } + } + return result.toArray(new IBinding[result.size()]); + } + + public IBinding[] find(String name) { + return getBindings(name.toCharArray()); + } + + public IBinding getBinding(IASTName name, boolean resolve) { + if (name instanceof ICPPASTTemplateId) + return null; + return getBinding(name.getSimpleID()); + } + + public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet acceptLocalBindings) { + return getBinding(name, resolve); + } + + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup) { + if (name instanceof ICPPASTTemplateId) + return IBinding.EMPTY_BINDING_ARRAY; + + if (prefixLookup) + return getPrefixBindings(name.getSimpleID()); + return getBindings(name.getSimpleID()); + } + + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, + IIndexFileSet acceptLocalBindings) { + return getBindings(name, resolve, prefixLookup); + } + + public ICPPClassType getClassType() { + return CPPClosureType.this; + } + + public ICPPMethod[] getImplicitMethods() { + return getMethods(); + } + + public ICPPConstructor[] getConstructors() { + return CPPClosureType.this.getConstructors(); + } + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java index 09324a31b5f..5e50718b1fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPImplicitFunction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2009 IBM Corporation and others. + * Copyright (c) 2005, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -27,8 +27,9 @@ public class CPPImplicitFunction extends CPPFunction { private ICPPParameter[] parms=null; private IScope scope=null; private ICPPFunctionType functionType=null; - private boolean takesVarArgs=false; - private char[] name=null; + private final boolean takesVarArgs; + private boolean isDeleted; + private final char[] name; public CPPImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, ICPPParameter[] parms, boolean takesVarArgs) { super( null ); @@ -82,8 +83,17 @@ public class CPPImplicitFunction extends CPPFunction { return takesVarArgs; } + @Override + public boolean isDeleted() { + return isDeleted; + } + @Override public IBinding getOwner() { return null; } + + public void setDeleted(boolean val) { + isDeleted= val; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPLambdaExpressionParameter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPLambdaExpressionParameter.java new file mode 100644 index 00000000000..3603c92f523 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPLambdaExpressionParameter.java @@ -0,0 +1,149 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Markus Schorn (Wind River Systems) - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.cpp; + +import org.eclipse.cdt.core.dom.ILinkage; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IScope; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.IValue; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType; +import org.eclipse.cdt.internal.core.dom.Linkage; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.core.runtime.PlatformObject; + +/** + * Binding for a c++ function parameter + */ +public class CPPLambdaExpressionParameter extends PlatformObject implements ICPPParameter { + private IType fType = null; + private IASTName fDeclaration = null; + + public CPPLambdaExpressionParameter(IASTName name) { + fDeclaration = name; + } + + public boolean isParameterPack() { + return getType() instanceof ICPPParameterPackType; + } + + public String getName() { + return new String(getNameCharArray()); + } + + public char[] getNameCharArray() { + return fDeclaration.getSimpleID(); + } + + public IScope getScope() { + return CPPVisitor.getContainingScope(fDeclaration); + } + + public IType getType() { + if (fType == null) { + IASTNode parent= fDeclaration.getParent(); + while (parent != null) { + if (parent instanceof ICPPASTParameterDeclaration) { + fType= CPPVisitor.createParameterType((ICPPASTParameterDeclaration) parent, false); + break; + } + parent= parent.getParent(); + } + } + return fType; + } + + public boolean isStatic() { + return false; + } + public String[] getQualifiedName() { + return new String[] { getName() }; + } + public char[][] getQualifiedNameCharArray() { + return new char[][] { getNameCharArray() }; + } + public boolean isGloballyQualified() { + return false; + } + + public boolean isExtern() { + //7.1.1-5 extern can not be used in the declaration of a parameter + return false; + } + + public boolean isMutable() { + //7.1.1-8 mutable can only apply to class members + return false; + } + + public boolean isAuto() { + return hasStorageClass(IASTDeclSpecifier.sc_auto); + } + + public boolean isRegister() { + return hasStorageClass(IASTDeclSpecifier.sc_register); + } + + private boolean hasStorageClass(int storage) { + IASTNode parent = fDeclaration.getParent(); + while (parent != null && !(parent instanceof IASTParameterDeclaration)) + parent = parent.getParent(); + if (parent != null) { + IASTDeclSpecifier declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier(); + if (declSpec.getStorageClass() == storage) + return true; + } + return false; + } + + public boolean hasDefaultValue() { + return false; + } + + public ILinkage getLinkage() { + return Linkage.CPP_LINKAGE; + } + + public boolean isExternC() { + return false; + } + + @Override + public String toString() { + String name = getName(); + return name.length() != 0 ? name : ""; //$NON-NLS-1$ + } + + public IBinding getOwner() { + IASTNode node= fDeclaration; + while (node != null && !(node instanceof ICPPASTLambdaExpression)) + node= node.getParent(); + + if (node instanceof ICPPASTLambdaExpression) { + IType type= ((ICPPASTLambdaExpression) node).getExpressionType(); + if (type instanceof IBinding) { + return (IBinding) type; + } + } + return null; + } + + public IValue getInitialValue() { + return null; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 6c7e64ed2c8..adfe0de5c70 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -96,6 +96,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; @@ -1322,7 +1323,12 @@ public class CPPSemantics { if (p instanceof IASTFunctionDefinition) { ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition) p).getDeclarator(); nodes = dtor.getParameters(); - } + } else if (p instanceof ICPPASTLambdaExpression) { + ICPPASTFunctionDeclarator dtor = ((ICPPASTLambdaExpression) p).getDeclarator(); + if (dtor != null) { + nodes = dtor.getParameters(); + } + } if (p instanceof ICPPASTCatchHandler) { parent = p; } else if (nodes == null || nodes.length == 0) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index cda9d215924..18562160336 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -15,11 +15,15 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*; +import java.util.ArrayList; import java.util.BitSet; import java.util.HashSet; +import java.util.List; import java.util.Set; +import org.eclipse.cdt.core.dom.ast.ASTGenericVisitor; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; @@ -80,7 +84,6 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; -import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; @@ -97,6 +100,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; @@ -161,6 +165,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPLabel; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPLambdaExpressionParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; @@ -603,16 +608,24 @@ public class CPPVisitor extends ASTQueries { if (parent instanceof IASTStandardFunctionDeclarator) { IASTStandardFunctionDeclarator fdtor = (IASTStandardFunctionDeclarator) param.getParent(); // Create parameter bindings only if the declarator declares a function - if (!(findOutermostDeclarator(fdtor).getParent() instanceof IASTDeclaration) || - findTypeRelevantDeclarator(fdtor) != fdtor) + if (findTypeRelevantDeclarator(fdtor) != fdtor) return null; - IASTParameterDeclaration[] params = fdtor.getParameters(); - int i= 0; - for (; i < params.length; i++) { - if (params[i] == param) - break; + + final IASTNode dtorParent= findOutermostDeclarator(fdtor).getParent(); + if (dtorParent instanceof ICPPASTLambdaExpression) { + return new CPPLambdaExpressionParameter(name); } - return new CPPParameter(name, i); + + if (dtorParent instanceof IASTDeclaration) { + IASTParameterDeclaration[] params = fdtor.getParameters(); + int i= 0; + for (; i < params.length; i++) { + if (params[i] == param) + break; + } + return new CPPParameter(name, i); + } + return null; } else if (parent instanceof ICPPASTTemplateDeclaration) { return CPPTemplates.createBinding(param); } @@ -894,14 +907,21 @@ public class CPPVisitor extends ASTQueries { while (parent.getParent() instanceof IASTDeclarator) parent = parent.getParent(); ASTNodeProperty prop = parent.getPropertyInParent(); - if (prop == IASTSimpleDeclaration.DECLARATOR) + if (prop == IASTSimpleDeclaration.DECLARATOR) { return dtor.getFunctionScope(); - else if (prop == IASTFunctionDefinition.DECLARATOR) { + } + if (prop == IASTFunctionDefinition.DECLARATOR) { final IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition) parent.getParent()).getBody(); if (body != null) return body.getScope(); return dtor.getFunctionScope(); - } + } + if (prop == ICPPASTLambdaExpression.DECLARATOR) { + final IASTCompoundStatement body = ((ICPPASTLambdaExpression) parent.getParent()).getBody(); + if (body != null) + return body.getScope(); + return dtor.getFunctionScope(); + } } } else if (parent instanceof ICPPASTTemplateDeclaration) { return CPPTemplates.getContainingScope(node); @@ -1222,95 +1242,37 @@ public class CPPVisitor extends ASTQueries { return null; } - public static class CollectProblemsAction extends CPPASTVisitor { - { - shouldVisitDeclarations = true; - shouldVisitExpressions = true; - shouldVisitStatements = true; - shouldVisitTypeIds = true; - } + private static class CollectProblemsAction extends ASTGenericVisitor { + private List fProblems = null; - private static final int DEFAULT_CHILDREN_LIST_SIZE = 8; - private IASTProblem[] problems = null; - int numFound = 0; + CollectProblemsAction() { + super(true); + } - public CollectProblemsAction() { - problems = new IASTProblem[DEFAULT_CHILDREN_LIST_SIZE]; - } - private void addProblem(IASTProblem problem) { - if (problems.length == numFound) { // if the found array is full, then double the array - IASTProblem[] old = problems; - problems = new IASTProblem[old.length * 2]; - for (int j = 0; j < old.length; ++j) - problems[j] = old[j]; - } - problems[numFound++] = problem; - } - - private IASTProblem[] removeNullFromProblems() { - if (problems[problems.length-1] != null) { // if the last element in the list is not null then return the list - return problems; - } else if (problems[0] == null) { // if the first element in the list is null, then return empty list - return new IASTProblem[0]; + if (fProblems == null) { + fProblems= new ArrayList(); } - - IASTProblem[] results = new IASTProblem[numFound]; - for (int i=0; i OPERATOR_CHARS.length + 1 && - CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) { - if (name[OPERATOR_CHARS.length] == ' ') { - result= !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1)); - } - } + final char[] name= method.getNameCharArray(); + if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' && + CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) { + return !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1)); } - return result; + return false; } /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java index 5473ead91b2..6cd2a680165 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPLinkage.java @@ -71,6 +71,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; @@ -273,6 +274,9 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { pdomBinding = createBinding(parent, binding, fileLocalRec[0]); if (pdomBinding != null) { getPDOM().putCachedResult(inputBinding, pdomBinding); + if (inputBinding instanceof CPPClosureType) { + addImplicitMethods(pdomBinding, (ICPPClassType) binding); + } } } catch (DOMException e) { throw new CoreException(Util.createStatus(e)); @@ -395,7 +399,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants { if (parent2 != null) { parent2.addChild(pdomBinding); } - if (parent2 != this) { + if (parent != this && parent2 != this) { insertIntoNestedBindingsIndex(pdomBinding); } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java index 5b2b6393340..980954445e2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/indexer/IndexerASTVisitor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2010 Wind River Systems, Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -14,9 +14,11 @@ import java.util.ArrayList; import java.util.List; import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTInitializer; @@ -25,7 +27,10 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTProblem; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; @@ -51,6 +56,7 @@ abstract public class IndexerASTVisitor extends ASTVisitor { shouldVisitInitializers= true; shouldVisitDeclSpecifiers= true; shouldVisitProblems= true; + shouldVisitExpressions= true; } public List getProblems() { @@ -112,13 +118,11 @@ abstract public class IndexerASTVisitor extends ASTVisitor { IASTName name= getLastInQualified(nestedDeclarator.getName()); visit(name, fDefinitionName); push(name, decl); - } - else if (decl instanceof IASTSimpleDeclaration) { + } else if (decl instanceof IASTSimpleDeclaration) { IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) decl; if (sdecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) { IASTDeclarator[] declarators= sdecl.getDeclarators(); - for (int i = 0; i < declarators.length; i++) { - IASTDeclarator declarator = declarators[i]; + for (IASTDeclarator declarator : declarators) { if (declarator.getPointerOperators().length == 0 && declarator.getNestedDeclarator() == null) { IASTName name= getLastInQualified(declarator.getName()); @@ -127,7 +131,7 @@ abstract public class IndexerASTVisitor extends ASTVisitor { } } } - } + } return PROCESS_CONTINUE; } @@ -185,4 +189,40 @@ abstract public class IndexerASTVisitor extends ASTVisitor { pop(initializer); return PROCESS_CONTINUE; } + + // Lambda expressions + @Override + public int visit(IASTExpression expr) { + if (expr instanceof ICPPASTLambdaExpression) { + return visit((ICPPASTLambdaExpression) expr); + } + return PROCESS_CONTINUE; + } + + private int visit(final ICPPASTLambdaExpression lambdaExpr) { + // Captures + for (ICPPASTCapture cap : lambdaExpr.getCaptures()) { + if (!cap.accept(this)) + return PROCESS_ABORT; + } + // Definition of closure type + final IASTName closureName = lambdaExpr.getClosureTypeName(); + visit(closureName, fDefinitionName); + + // Definition of call operator + IASTName callOp= lambdaExpr.getFunctionCallOperatorName(); + visit(callOp, closureName); + push(callOp, lambdaExpr); + + ICPPASTFunctionDeclarator dtor = lambdaExpr.getDeclarator(); + if (dtor != null && !dtor.accept(this)) + return PROCESS_ABORT; + + IASTCompoundStatement body = lambdaExpr.getBody(); + if (body != null && !body.accept(this)) + return PROCESS_ABORT; + + pop(lambdaExpr); + return PROCESS_SKIP; + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CppCallHierarchyTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CppCallHierarchyTest.java index 96a143e7808..284a6b0c698 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CppCallHierarchyTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/callhierarchy/CppCallHierarchyTest.java @@ -465,4 +465,41 @@ public class CppCallHierarchyTest extends CallHierarchyBaseTest { checkTreeNode(tree, 0, 0, "testchar()"); checkTreeNode(tree, 0, 1, null); } + + // void a() {} + // auto b= [] {a();}; + // void c() { + // b(); + // } + // void d() { + // []{c();}(); + // } + public void testClosures_316307() throws Exception { + StringBuffer[] content= getContentsForTest(1); + String source = content[0].toString(); + IFile file= createFile(getProject(), "testClosures.cpp", source); + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + waitForIndexer(fIndex, file, CallHierarchyBaseTest.INDEXER_WAIT_TIME); + CCorePlugin.getIndexManager().joinIndexer(INDEXER_WAIT_TIME, npm()); + + CEditor editor= openEditor(file); + int pos= source.indexOf("a("); + editor.selectAndReveal(pos, 1); + openCallHierarchy(editor, true); + Tree tree = getCHTreeViewer().getTree(); + + checkTreeNode(tree, 0, "a()"); + TreeItem node = checkTreeNode(tree, 0, 0, "(anonymous)::operator ()()"); + expandTreeItem(node); + node= checkTreeNode(node, 0, "c()"); + checkTreeNode(node, 1, null); + expandTreeItem(node); + node= checkTreeNode(node, 0, "(anonymous)::operator ()()"); + checkTreeNode(node, 1, null); + expandTreeItem(node); + node= checkTreeNode(node, 0, "d()"); + checkTreeNode(node, 1, null); + expandTreeItem(node); + checkTreeNode(node, 0, null); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java index b37af1a34d2..7b1aec94966 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java @@ -405,6 +405,9 @@ public class SemanticHighlightings { @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); + if (node instanceof IASTImplicitName) + return false; + if (node instanceof IASTName) { IASTName name= (IASTName)node; if (!name.isReference()) { @@ -659,6 +662,9 @@ public class SemanticHighlightings { @Override public boolean consumes(SemanticToken token) { IASTNode node= token.getNode(); + if (node instanceof IASTImplicitName) + return false; + if (node instanceof IASTName) { IASTName name= (IASTName)node; if (name.isDeclaration()) { @@ -1989,17 +1995,21 @@ public class SemanticHighlightings { public boolean consumes(SemanticToken token) { IASTNode node = token.getNode(); // so far we only have implicit names for overloaded operators and destructors, so this works - if(node instanceof IASTImplicitName) { + if (node instanceof IASTImplicitName) { IASTImplicitName name = (IASTImplicitName) node; - IBinding binding = name.resolveBinding(); - if(binding instanceof ICPPMethod && !(binding instanceof IProblemBinding) && ((ICPPMethod)binding).isImplicit()) { - return false; + if (name.isReference() && name.isOperator()) { + IBinding binding = name.resolveBinding(); + if (binding instanceof ICPPMethod && !(binding instanceof IProblemBinding) + && ((ICPPMethod) binding).isImplicit()) { + return false; + } + char[] chars = name.toCharArray(); + if (chars[0] == '~' || OverloadableOperator.isNew(chars) + || OverloadableOperator.isDelete(chars)) { + return false; + } + return true; } - char[] chars = name.toCharArray(); - if(chars[0] == '~' || OverloadableOperator.isNew(chars) || OverloadableOperator.isDelete(chars)) { - return false; - } - return true; } return false; } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java index 12e793bfda3..191090d73cd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/viewsupport/IndexUI.java @@ -417,6 +417,9 @@ public class IndexUI { if (ast != null) { final IASTNodeSelector nodeSelector = ast.getNodeSelector(null); IASTName name= nodeSelector.findEnclosingName(offset, length); + if (name == null) { + name= nodeSelector.findImplicitName(offset, length); + } if (name != null && name.getParent() instanceof IASTPreprocessorMacroExpansion) { IASTFileLocation floc= name.getParent().getFileLocation(); IASTNode node= nodeSelector.findEnclosingNodeInExpansion(floc.getNodeOffset(), floc.getNodeLength());