1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 316307: [C++0x] Semantics for lamda expressions.

This commit is contained in:
Markus Schorn 2010-08-24 08:53:50 +00:00
parent b6d83a4804
commit 9cb98d05cf
19 changed files with 889 additions and 154 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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 <code>null</code>
* 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 <code>null</code>
* when creating AST for content assist.

View file

@ -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();
}

View file

@ -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);

View file

@ -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;
}
/**

View file

@ -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() {

View file

@ -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<IBinding> result= new ArrayList<IBinding>();
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();
}
}
}

View file

@ -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;
}
}

View file

@ -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 : "<unnamed>"; //$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;
}
}

View file

@ -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) {

View file

@ -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<IASTProblem> 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>();
}
IASTProblem[] results = new IASTProblem[numFound];
for (int i=0; i<results.length; i++)
results[i] = problems[i];
fProblems.add(problem);
}
return results;
}
public IASTProblem[] getProblems() {
return removeNullFromProblems();
if (fProblems == null)
return new IASTProblem[0];
return fProblems.toArray(new IASTProblem[fProblems.size()]);
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processDeclaration(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
*/
@Override
public int visit(IASTDeclaration declaration) {
if (declaration instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) declaration).getProblem());
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processExpression(org.eclipse.cdt.core.dom.ast.IASTExpression)
*/
@Override
public int visit(IASTExpression expression) {
if (expression instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) expression).getProblem());
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processStatement(org.eclipse.cdt.core.dom.ast.IASTStatement)
*/
@Override
public int visit(IASTStatement statement) {
if (statement instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) statement).getProblem());
return PROCESS_CONTINUE;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.c.CVisitor.CBaseVisitorAction#processTypeId(org.eclipse.cdt.core.dom.ast.IASTTypeId)
*/
@Override
public int visit(IASTTypeId typeId) {
if (typeId instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) typeId).getProblem());
public int genericVisit(IASTNode node) {
if (node instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) node).getProblem());
return PROCESS_CONTINUE;
}
}
public static class CollectDeclarationsAction extends CPPASTVisitor {
public static class CollectDeclarationsAction extends ASTVisitor {
private static final int DEFAULT_LIST_SIZE = 8;
private IASTName[] decls;
private IBinding[] bindings;
@ -1484,7 +1446,7 @@ public class CPPVisitor extends ASTQueries {
return binding;
}
public static class CollectReferencesAction extends CPPASTVisitor {
public static class CollectReferencesAction extends ASTVisitor {
private static final int DEFAULT_LIST_SIZE = 8;
private IASTName[] refs;
private IBinding[] bindings;
@ -1664,11 +1626,7 @@ public class CPPVisitor extends ASTQueries {
}
private static IType createType(IType returnType, ICPPASTFunctionDeclarator fnDtor) {
ICPPASTParameterDeclaration[] params = fnDtor.getParameters();
IType[] pTypes = new IType[params.length];
for (int i = 0; i < params.length; i++) {
pTypes[i]= createParameterType(params[i], true);
}
IType[] pTypes = createParameterTypes(fnDtor);
IASTName name = fnDtor.getName();
if (name instanceof ICPPASTQualifiedName) {
@ -1690,6 +1648,15 @@ public class CPPVisitor extends ASTQueries {
return type;
}
public static IType[] createParameterTypes(ICPPASTFunctionDeclarator fnDtor) {
ICPPASTParameterDeclaration[] params = fnDtor.getParameters();
IType[] pTypes = new IType[params.length];
for (int i = 0; i < params.length; i++) {
pTypes[i]= createParameterType(params[i], true);
}
return pTypes;
}
/**
* Creates the type for a parameter declaration.
*/

View file

@ -989,7 +989,9 @@ public class Conversions {
// 4.8 floating point conversion
// 4.9 floating-integral conversion
if (s instanceof IBasicType) {
// 4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
if (((IBasicType) s).getKind() == Kind.eVoid)
return false;
cost.setRank(Rank.CONVERSION);
cost.setCouldNarrow();
return true;
@ -1087,4 +1089,41 @@ public class Conversions {
}
return false;
}
/**
* 4.1
*/
public static IType lvalue_to_rvalue(IType type) {
IType nested= SemanticUtil.getNestedType(type, TDEF | REF);
if (nested == null || nested == type || nested instanceof IArrayType || nested instanceof ICPPFunctionType) {
return type;
}
IType unqualified= SemanticUtil.getNestedType(nested, TDEF | ALLCVQ);
if (unqualified instanceof ICPPClassType)
return nested;
return unqualified;
}
/**
* 4.2
*/
public static IType array_to_pointer(IType type) {
IType nested= SemanticUtil.getNestedType(type, TDEF);
if (nested instanceof IArrayType) {
return new CPPPointerType(((IArrayType) nested).getType());
}
return type;
}
/**
* 4.3
*/
public static IType function_to_pointer(IType type) {
IType nested= SemanticUtil.getNestedType(type, TDEF);
if (nested instanceof IFunctionType) {
return new CPPPointerType(nested);
}
return type;
}
}

View file

@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
@ -28,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
@ -156,17 +156,12 @@ public class SemanticUtil {
* @return true if the specified method is a conversion operator
*/
public static final boolean isConversionOperator(ICPPMethod method) {
boolean result= false;
if (!method.isImplicit()) {
final char[] name= method.getNameCharArray();
if (name.length > 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;
}
/**

View file

@ -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);
}
}

View file

@ -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<IASTProblem> 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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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());