1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +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); // return abs(a) < abs(b);
// }); // });
// } // }
public void _testLambdaExpression_316307b() throws Exception { public void testLambdaExpression_316307b() throws Exception {
String code= getAboveComment(); String code= getAboveComment();
parseAndCheckBindings(code); parseAndCheckBindings(code);
} }

View file

@ -869,7 +869,6 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
// foo/*i*/(23489); // IASTLiteralExpression // foo/*i*/(23489); // IASTLiteralExpression
// foo/*j*/(sizeof(C));/*9*/ // IASTTypeIdExpression // foo/*j*/(sizeof(C));/*9*/ // IASTTypeIdExpression
// foo/*k*/(*cp);/*10*/ // IASTUnaryExpression // foo/*k*/(*cp);/*10*/ // IASTUnaryExpression
// foo/*l*/(delete cp);/*11*/ // ICPPASTDeleteExpression
// foo/*m*/(new C());/*12*/ // ICPPASTNewExpression // foo/*m*/(new C());/*12*/ // ICPPASTNewExpression
// // ?? foo/*n*/(); // ICPPASTSimpleTypeConstructorExpression // // ?? foo/*n*/(); // ICPPASTSimpleTypeConstructorExpression
// // ?? foo/*o*/(); // ICPPASTTypenameExprssion // // ?? foo/*o*/(); // ICPPASTTypenameExprssion
@ -916,9 +915,6 @@ public abstract class IndexCPPBindingResolutionTest extends IndexBindingResoluti
IBinding b10 = getBindingFromASTName("foo/*k*/", 3); IBinding b10 = getBindingFromASTName("foo/*k*/", 3);
IBinding b10a = getBindingFromASTName("cp);/*10*/", 2); 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 b12 = getBindingFromASTName("foo/*m*/", 3);
IBinding b12a = getBindingFromASTName("C());/*12*/", 1); IBinding b12a = getBindingFromASTName("C());/*12*/", 1);
// IBinding b13 = getBindingFromASTName(ast, "foo/*n*/", 3); // 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.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpression; 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. * 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. * @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented 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 CAPTURE = new ASTNodeProperty("ICPPASTLambdaExpression - CAPTURE [ICPPASTCapture]"); //$NON-NLS-1$
ASTNodeProperty DECLARATOR = new ASTNodeProperty("ICPPASTLambdaExpression - DECLARATOR [ICPPASTFunctionDeclarator]"); //$NON-NLS-1$ ASTNodeProperty DECLARATOR = new ASTNodeProperty("ICPPASTLambdaExpression - DECLARATOR [ICPPASTFunctionDeclarator]"); //$NON-NLS-1$
ASTNodeProperty BODY = new ASTNodeProperty("ICPPASTLambdaExpression - BODY [IASTCompoundStatement]"); //$NON-NLS-1$ ASTNodeProperty BODY = new ASTNodeProperty("ICPPASTLambdaExpression - BODY [IASTCompoundStatement]"); //$NON-NLS-1$
@ -41,12 +43,23 @@ public interface ICPPASTLambdaExpression extends IASTExpression {
*/ */
ICPPASTCapture[] getCaptures(); 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> * Returns the lambda declarator for this lambda expression, or <code>null</code>
* in case it was not specified. * in case it was not specified.
*/ */
ICPPASTFunctionDeclarator getDeclarator(); 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> * Returns the compound statement of this lambda expression. Can be <code>null</code>
* when creating AST for content assist. * 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * 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.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; 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.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
@ -91,23 +92,29 @@ public class CPPASTConversionName extends CPPASTNameBase implements ICPPASTConve
public char[] toCharArray() { public char[] toCharArray() {
if (fName == null) { if (fName == null) {
IType t= null;
if (typeId != null) {
t= CPPVisitor.createType(typeId);
}
fName= createName(t, typeId);
}
return fName;
}
public static char[] createName(IType t, IASTNode typeId) {
StringBuilder buf= new StringBuilder(); StringBuilder buf= new StringBuilder();
buf.append(Keywords.cOPERATOR); buf.append(Keywords.cOPERATOR);
buf.append(' '); buf.append(' ');
if (typeId != null) {
IType t= CPPVisitor.createType(typeId);
if (t != null) { if (t != null) {
buf.append(ASTTypeUtil.getType(t, true)); buf.append(ASTTypeUtil.getType(t, true));
} else { } else {
buf.append(typeId.getRawSignature()); buf.append(typeId.getRawSignature());
WHITESPACE_SEQ.matcher(buf).replaceAll(" "); //$NON-NLS-1$ WHITESPACE_SEQ.matcher(buf).replaceAll(" "); //$NON-NLS-1$
} }
}
final int len= buf.length(); final int len= buf.length();
fName= new char[len]; char[] name= new char[len];
buf.getChars(0, len, fName, 0); buf.getChars(0, len, name, 0);
} return name;
return fName;
} }
public char[] getSimpleID() { public char[] getSimpleID() {

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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; 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.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
@ -109,8 +110,11 @@ public class CPPASTFunctionCallExpression extends ASTNode implements
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) { if (implicitNames == null) {
ICPPFunction overload = getOperator(); ICPPFunction overload = getOperator();
if (overload == null || overload instanceof CPPImplicitFunction) if (overload == null || overload instanceof CPPImplicitFunction) {
if (!(overload instanceof ICPPMethod) || ((ICPPMethod) overload).isImplicit()) {
return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; return implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
}
// create separate implicit names for the two brackets // create separate implicit names for the two brackets
CPPASTImplicitName n1 = new CPPASTImplicitName(OverloadableOperator.PAREN, this); 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 { public class CPPASTImplicitName extends CPPASTName implements IASTImplicitName {
private boolean alternate; private boolean alternate;
private boolean isOperator; private boolean isOperator;
private boolean isDefinition= false;
public CPPASTImplicitName(char[] name, IASTNode parent) { public CPPASTImplicitName(char[] name, IASTNode parent) {
super(name); super(name);
@ -74,12 +75,16 @@ public class CPPASTImplicitName extends CPPASTName implements IASTImplicitName {
@Override @Override
public boolean isDefinition() { public boolean isDefinition() {
return false; return isDefinition;
} }
@Override @Override
public boolean isReference() { 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.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpression; 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.ICPPASTCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; 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;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
@ -29,8 +30,13 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
private CaptureDefault fCaptureDefault; private CaptureDefault fCaptureDefault;
private ICPPASTCapture[] fCaptures; private ICPPASTCapture[] fCaptures;
private ICPPASTFunctionDeclarator fDeclarator; private ICPPASTFunctionDeclarator fDeclarator;
private IASTCompoundStatement fBody; private IASTCompoundStatement fBody;
private CPPClosureType fClosureType;
private IASTImplicitName fClosureTypeName;
private IASTImplicitName fImplicitFunctionCallName;
public CPPASTLambdaExpression() { public CPPASTLambdaExpression() {
fCaptureDefault= CaptureDefault.UNSPECIFIED; fCaptureDefault= CaptureDefault.UNSPECIFIED;
} }
@ -59,6 +65,41 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
return result; 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 @Override
public boolean accept(ASTVisitor visitor) { public boolean accept(ASTVisitor visitor) {
if (visitor.shouldVisitExpressions) { 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) { if (fCaptures != null) {
for (ICPPASTCapture cap : fCaptures) { for (ICPPASTCapture cap : fCaptures) {
if (cap != null && !cap.accept(visitor)) if (cap != null && !cap.accept(visitor))
@ -77,6 +121,10 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
} }
if (fDeclarator != null && !fDeclarator.accept(visitor)) if (fDeclarator != null && !fDeclarator.accept(visitor))
return false; return false;
if (visitor.shouldVisitImplicitNames && !getFunctionCallOperatorName().accept(visitor))
return false;
if (fBody != null && !fBody.accept(visitor)) if (fBody != null && !fBody.accept(visitor))
return false; return false;
@ -133,9 +181,11 @@ public class CPPASTLambdaExpression extends ASTNode implements ICPPASTLambdaExpr
fDeclarator= dtor; fDeclarator= dtor;
} }
public IType getExpressionType() { public CPPClosureType getExpressionType() {
// mstodo type for lambda expressions if (fClosureType == null)
return null; fClosureType= new CPPClosureType(this);
return fClosureType;
} }
public boolean isLValue() { 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -27,8 +27,9 @@ public class CPPImplicitFunction extends CPPFunction {
private ICPPParameter[] parms=null; private ICPPParameter[] parms=null;
private IScope scope=null; private IScope scope=null;
private ICPPFunctionType functionType=null; private ICPPFunctionType functionType=null;
private boolean takesVarArgs=false; private final boolean takesVarArgs;
private char[] name=null; private boolean isDeleted;
private final char[] name;
public CPPImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, ICPPParameter[] parms, boolean takesVarArgs) { public CPPImplicitFunction(char[] name, IScope scope, ICPPFunctionType type, ICPPParameter[] parms, boolean takesVarArgs) {
super( null ); super( null );
@ -82,8 +83,17 @@ public class CPPImplicitFunction extends CPPFunction {
return takesVarArgs; return takesVarArgs;
} }
@Override
public boolean isDeleted() {
return isDeleted;
}
@Override @Override
public IBinding getOwner() { public IBinding getOwner() {
return null; 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.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; 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.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.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias;
@ -1322,6 +1323,11 @@ public class CPPSemantics {
if (p instanceof IASTFunctionDefinition) { if (p instanceof IASTFunctionDefinition) {
ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition) p).getDeclarator(); ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition) p).getDeclarator();
nodes = dtor.getParameters(); nodes = dtor.getParameters();
} else if (p instanceof ICPPASTLambdaExpression) {
ICPPASTFunctionDeclarator dtor = ((ICPPASTLambdaExpression) p).getDeclarator();
if (dtor != null) {
nodes = dtor.getParameters();
}
} }
if (p instanceof ICPPASTCatchHandler) { if (p instanceof ICPPASTCatchHandler) {
parent = p; parent = p;

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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import java.util.ArrayList;
import java.util.BitSet; import java.util.BitSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; 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.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.EScopeKind; import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; 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.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable; 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.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; 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.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement; 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.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.ICPPASTLinkageSpecification;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceAlias; 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.CPPFunctionTemplate;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; 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.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.CPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplate;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
@ -603,9 +608,15 @@ public class CPPVisitor extends ASTQueries {
if (parent instanceof IASTStandardFunctionDeclarator) { if (parent instanceof IASTStandardFunctionDeclarator) {
IASTStandardFunctionDeclarator fdtor = (IASTStandardFunctionDeclarator) param.getParent(); IASTStandardFunctionDeclarator fdtor = (IASTStandardFunctionDeclarator) param.getParent();
// Create parameter bindings only if the declarator declares a function // Create parameter bindings only if the declarator declares a function
if (!(findOutermostDeclarator(fdtor).getParent() instanceof IASTDeclaration) || if (findTypeRelevantDeclarator(fdtor) != fdtor)
findTypeRelevantDeclarator(fdtor) != fdtor)
return null; return null;
final IASTNode dtorParent= findOutermostDeclarator(fdtor).getParent();
if (dtorParent instanceof ICPPASTLambdaExpression) {
return new CPPLambdaExpressionParameter(name);
}
if (dtorParent instanceof IASTDeclaration) {
IASTParameterDeclaration[] params = fdtor.getParameters(); IASTParameterDeclaration[] params = fdtor.getParameters();
int i= 0; int i= 0;
for (; i < params.length; i++) { for (; i < params.length; i++) {
@ -613,6 +624,8 @@ public class CPPVisitor extends ASTQueries {
break; break;
} }
return new CPPParameter(name, i); return new CPPParameter(name, i);
}
return null;
} else if (parent instanceof ICPPASTTemplateDeclaration) { } else if (parent instanceof ICPPASTTemplateDeclaration) {
return CPPTemplates.createBinding(param); return CPPTemplates.createBinding(param);
} }
@ -894,14 +907,21 @@ public class CPPVisitor extends ASTQueries {
while (parent.getParent() instanceof IASTDeclarator) while (parent.getParent() instanceof IASTDeclarator)
parent = parent.getParent(); parent = parent.getParent();
ASTNodeProperty prop = parent.getPropertyInParent(); ASTNodeProperty prop = parent.getPropertyInParent();
if (prop == IASTSimpleDeclaration.DECLARATOR) if (prop == IASTSimpleDeclaration.DECLARATOR) {
return dtor.getFunctionScope(); return dtor.getFunctionScope();
else if (prop == IASTFunctionDefinition.DECLARATOR) { }
if (prop == IASTFunctionDefinition.DECLARATOR) {
final IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition) parent.getParent()).getBody(); final IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition) parent.getParent()).getBody();
if (body != null) if (body != null)
return body.getScope(); return body.getScope();
return dtor.getFunctionScope(); 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) { } else if (parent instanceof ICPPASTTemplateDeclaration) {
return CPPTemplates.getContainingScope(node); return CPPTemplates.getContainingScope(node);
@ -1222,95 +1242,37 @@ public class CPPVisitor extends ASTQueries {
return null; return null;
} }
public static class CollectProblemsAction extends CPPASTVisitor { private static class CollectProblemsAction extends ASTGenericVisitor {
{ private List<IASTProblem> fProblems = null;
shouldVisitDeclarations = true;
shouldVisitExpressions = true;
shouldVisitStatements = true;
shouldVisitTypeIds = true;
}
private static final int DEFAULT_CHILDREN_LIST_SIZE = 8; CollectProblemsAction() {
private IASTProblem[] problems = null; super(true);
int numFound = 0;
public CollectProblemsAction() {
problems = new IASTProblem[DEFAULT_CHILDREN_LIST_SIZE];
} }
private void addProblem(IASTProblem problem) { private void addProblem(IASTProblem problem) {
if (problems.length == numFound) { // if the found array is full, then double the array if (fProblems == null) {
IASTProblem[] old = problems; fProblems= new ArrayList<IASTProblem>();
problems = new IASTProblem[old.length * 2];
for (int j = 0; j < old.length; ++j)
problems[j] = old[j];
} }
problems[numFound++] = problem; fProblems.add(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];
}
IASTProblem[] results = new IASTProblem[numFound];
for (int i=0; i<results.length; i++)
results[i] = problems[i];
return results;
} }
public IASTProblem[] getProblems() { 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 @Override
public int visit(IASTDeclaration declaration) { public int genericVisit(IASTNode node) {
if (declaration instanceof IASTProblemHolder) if (node instanceof IASTProblemHolder)
addProblem(((IASTProblemHolder) declaration).getProblem()); addProblem(((IASTProblemHolder) node).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());
return PROCESS_CONTINUE; return PROCESS_CONTINUE;
} }
} }
public static class CollectDeclarationsAction extends CPPASTVisitor { public static class CollectDeclarationsAction extends ASTVisitor {
private static final int DEFAULT_LIST_SIZE = 8; private static final int DEFAULT_LIST_SIZE = 8;
private IASTName[] decls; private IASTName[] decls;
private IBinding[] bindings; private IBinding[] bindings;
@ -1484,7 +1446,7 @@ public class CPPVisitor extends ASTQueries {
return binding; return binding;
} }
public static class CollectReferencesAction extends CPPASTVisitor { public static class CollectReferencesAction extends ASTVisitor {
private static final int DEFAULT_LIST_SIZE = 8; private static final int DEFAULT_LIST_SIZE = 8;
private IASTName[] refs; private IASTName[] refs;
private IBinding[] bindings; private IBinding[] bindings;
@ -1664,11 +1626,7 @@ public class CPPVisitor extends ASTQueries {
} }
private static IType createType(IType returnType, ICPPASTFunctionDeclarator fnDtor) { private static IType createType(IType returnType, ICPPASTFunctionDeclarator fnDtor) {
ICPPASTParameterDeclaration[] params = fnDtor.getParameters(); IType[] pTypes = createParameterTypes(fnDtor);
IType[] pTypes = new IType[params.length];
for (int i = 0; i < params.length; i++) {
pTypes[i]= createParameterType(params[i], true);
}
IASTName name = fnDtor.getName(); IASTName name = fnDtor.getName();
if (name instanceof ICPPASTQualifiedName) { if (name instanceof ICPPASTQualifiedName) {
@ -1690,6 +1648,15 @@ public class CPPVisitor extends ASTQueries {
return type; 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. * Creates the type for a parameter declaration.
*/ */

View file

@ -989,7 +989,9 @@ public class Conversions {
// 4.8 floating point conversion // 4.8 floating point conversion
// 4.9 floating-integral conversion // 4.9 floating-integral conversion
if (s instanceof IBasicType) { 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.setRank(Rank.CONVERSION);
cost.setCouldNarrow(); cost.setCouldNarrow();
return true; return true;
@ -1087,4 +1089,41 @@ public class Conversions {
} }
return false; 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.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType; 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.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType; 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.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; 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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; 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 * @return true if the specified method is a conversion operator
*/ */
public static final boolean isConversionOperator(ICPPMethod method) { public static final boolean isConversionOperator(ICPPMethod method) {
boolean result= false;
if (!method.isImplicit()) {
final char[] name= method.getNameCharArray(); final char[] name= method.getNameCharArray();
if (name.length > OPERATOR_CHARS.length + 1 && if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' &&
CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) { CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) {
if (name[OPERATOR_CHARS.length] == ' ') { return !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1));
result= !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1));
} }
} return false;
}
return result;
} }
/** /**

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.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; 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.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.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameterPackType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; 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]); pdomBinding = createBinding(parent, binding, fileLocalRec[0]);
if (pdomBinding != null) { if (pdomBinding != null) {
getPDOM().putCachedResult(inputBinding, pdomBinding); getPDOM().putCachedResult(inputBinding, pdomBinding);
if (inputBinding instanceof CPPClosureType) {
addImplicitMethods(pdomBinding, (ICPPClassType) binding);
}
} }
} catch (DOMException e) { } catch (DOMException e) {
throw new CoreException(Util.createStatus(e)); throw new CoreException(Util.createStatus(e));
@ -395,7 +399,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (parent2 != null) { if (parent2 != null) {
parent2.addChild(pdomBinding); parent2.addChild(pdomBinding);
} }
if (parent2 != this) { if (parent != this && parent2 != this) {
insertIntoNestedBindingsIndex(pdomBinding); 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -14,9 +14,11 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.cdt.core.dom.ast.ASTVisitor; 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.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; 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.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTInitializer; 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.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.c.ICASTCompositeTypeSpecifier; 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.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.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -51,6 +56,7 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
shouldVisitInitializers= true; shouldVisitInitializers= true;
shouldVisitDeclSpecifiers= true; shouldVisitDeclSpecifiers= true;
shouldVisitProblems= true; shouldVisitProblems= true;
shouldVisitExpressions= true;
} }
public List<IASTProblem> getProblems() { public List<IASTProblem> getProblems() {
@ -112,13 +118,11 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
IASTName name= getLastInQualified(nestedDeclarator.getName()); IASTName name= getLastInQualified(nestedDeclarator.getName());
visit(name, fDefinitionName); visit(name, fDefinitionName);
push(name, decl); push(name, decl);
} } else if (decl instanceof IASTSimpleDeclaration) {
else if (decl instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) decl; IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) decl;
if (sdecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) { if (sdecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) {
IASTDeclarator[] declarators= sdecl.getDeclarators(); IASTDeclarator[] declarators= sdecl.getDeclarators();
for (int i = 0; i < declarators.length; i++) { for (IASTDeclarator declarator : declarators) {
IASTDeclarator declarator = declarators[i];
if (declarator.getPointerOperators().length == 0 && if (declarator.getPointerOperators().length == 0 &&
declarator.getNestedDeclarator() == null) { declarator.getNestedDeclarator() == null) {
IASTName name= getLastInQualified(declarator.getName()); IASTName name= getLastInQualified(declarator.getName());
@ -185,4 +189,40 @@ abstract public class IndexerASTVisitor extends ASTVisitor {
pop(initializer); pop(initializer);
return PROCESS_CONTINUE; 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, 0, "testchar()");
checkTreeNode(tree, 0, 1, null); 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 @Override
public boolean consumes(SemanticToken token) { public boolean consumes(SemanticToken token) {
IASTNode node= token.getNode(); IASTNode node= token.getNode();
if (node instanceof IASTImplicitName)
return false;
if (node instanceof IASTName) { if (node instanceof IASTName) {
IASTName name= (IASTName)node; IASTName name= (IASTName)node;
if (!name.isReference()) { if (!name.isReference()) {
@ -659,6 +662,9 @@ public class SemanticHighlightings {
@Override @Override
public boolean consumes(SemanticToken token) { public boolean consumes(SemanticToken token) {
IASTNode node= token.getNode(); IASTNode node= token.getNode();
if (node instanceof IASTImplicitName)
return false;
if (node instanceof IASTName) { if (node instanceof IASTName) {
IASTName name= (IASTName)node; IASTName name= (IASTName)node;
if (name.isDeclaration()) { if (name.isDeclaration()) {
@ -1989,18 +1995,22 @@ public class SemanticHighlightings {
public boolean consumes(SemanticToken token) { public boolean consumes(SemanticToken token) {
IASTNode node = token.getNode(); IASTNode node = token.getNode();
// so far we only have implicit names for overloaded operators and destructors, so this works // 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; IASTImplicitName name = (IASTImplicitName) node;
if (name.isReference() && name.isOperator()) {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
if(binding instanceof ICPPMethod && !(binding instanceof IProblemBinding) && ((ICPPMethod)binding).isImplicit()) { if (binding instanceof ICPPMethod && !(binding instanceof IProblemBinding)
&& ((ICPPMethod) binding).isImplicit()) {
return false; return false;
} }
char[] chars = name.toCharArray(); char[] chars = name.toCharArray();
if(chars[0] == '~' || OverloadableOperator.isNew(chars) || OverloadableOperator.isDelete(chars)) { if (chars[0] == '~' || OverloadableOperator.isNew(chars)
|| OverloadableOperator.isDelete(chars)) {
return false; return false;
} }
return true; return true;
} }
}
return false; return false;
} }
} }

View file

@ -417,6 +417,9 @@ public class IndexUI {
if (ast != null) { if (ast != null) {
final IASTNodeSelector nodeSelector = ast.getNodeSelector(null); final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);
IASTName name= nodeSelector.findEnclosingName(offset, length); IASTName name= nodeSelector.findEnclosingName(offset, length);
if (name == null) {
name= nodeSelector.findImplicitName(offset, length);
}
if (name != null && name.getParent() instanceof IASTPreprocessorMacroExpansion) { if (name != null && name.getParent() instanceof IASTPreprocessorMacroExpansion) {
IASTFileLocation floc= name.getParent().getFileLocation(); IASTFileLocation floc= name.getParent().getFileLocation();
IASTNode node= nodeSelector.findEnclosingNodeInExpansion(floc.getNodeOffset(), floc.getNodeLength()); IASTNode node= nodeSelector.findEnclosingNodeInExpansion(floc.getNodeOffset(), floc.getNodeLength());