1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 00:45:28 +02:00

Bug 367611: Implicit names for begin() and end() in range based for loop.

This commit is contained in:
Markus Schorn 2012-01-05 11:21:02 +01:00
parent 5b0b6666ea
commit 545ae7e7f9
4 changed files with 135 additions and 41 deletions

View file

@ -13,6 +13,7 @@ package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IScope;
@ -24,7 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IScope;
* @noimplement This interface is not intended to be implemented by clients.
* @since 5.3
*/
public interface ICPPASTRangeBasedForStatement extends IASTStatement {
public interface ICPPASTRangeBasedForStatement extends IASTStatement, IASTImplicitNameOwner {
public static final ASTNodeProperty DECLARATION = new ASTNodeProperty(
"ICPPASTRangeBasedForStatement.DECLARATION [IASTDeclaration]"); //$NON-NLS-1$
public static final ASTNodeProperty INITIALIZER = new ASTNodeProperty(
@ -53,8 +54,10 @@ public interface ICPPASTRangeBasedForStatement extends IASTStatement {
*/
public IScope getScope();
@Override
public ICPPASTRangeBasedForStatement copy();
@Override
public ICPPASTRangeBasedForStatement copy(CopyStyle style);

View file

@ -10,15 +10,26 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.CVTYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
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.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/**
* Range based for loop in c++.
@ -28,14 +39,17 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
private IASTDeclaration fDeclaration;
private IASTInitializerClause fInitClause;
private IASTStatement fBody;
private IASTImplicitName[] fImplicitNames;
public CPPASTRangeBasedForStatement() {
}
public CPPASTRangeBasedForStatement copy() {
@Override
public CPPASTRangeBasedForStatement copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public CPPASTRangeBasedForStatement copy(CopyStyle style) {
CPPASTRangeBasedForStatement copy = new CPPASTRangeBasedForStatement();
copy.setDeclaration(fDeclaration == null ? null : fDeclaration.copy(style));
@ -48,11 +62,13 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
return copy;
}
@Override
public IASTDeclaration getDeclaration() {
return fDeclaration;
}
public void setDeclaration(IASTDeclaration declaration) {
@Override
public void setDeclaration(IASTDeclaration declaration) {
assertNotFrozen();
this.fDeclaration = declaration;
if (declaration != null) {
@ -61,11 +77,13 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
}
}
public IASTInitializerClause getInitializerClause() {
@Override
public IASTInitializerClause getInitializerClause() {
return fInitClause;
}
public void setInitializerClause(IASTInitializerClause initClause) {
@Override
public void setInitializerClause(IASTInitializerClause initClause) {
assertNotFrozen();
fInitClause = initClause;
if (initClause != null) {
@ -74,10 +92,12 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
}
}
public IASTStatement getBody() {
@Override
public IASTStatement getBody() {
return fBody;
}
@Override
public void setBody(IASTStatement statement) {
assertNotFrozen();
fBody = statement;
@ -87,12 +107,72 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
}
}
@Override
public IScope getScope() {
if (fScope == null)
fScope = new CPPBlockScope(this);
return fScope;
}
@Override
public IASTImplicitName[] getImplicitNames() {
if (fImplicitNames == null) {
IASTInitializerClause forInit = getInitializerClause();
final ASTNode position = (ASTNode) forInit;
if (forInit instanceof IASTExpression) {
final IASTExpression forInitExpr = (IASTExpression) forInit;
IType type= SemanticUtil.getNestedType(forInitExpr.getExpressionType(), TDEF|CVTYPE);
if (type instanceof IArrayType) {
fImplicitNames= IASTImplicitName.EMPTY_NAME_ARRAY;
} else if (type instanceof ICPPClassType) {
ICPPClassType ct= (ICPPClassType) type;
if (CPPSemantics.findBindings(ct.getCompositeScope(), CPPVisitor.BEGIN_STR, true).length > 0) {
CPPASTName name = new CPPASTName(CPPVisitor.BEGIN);
name.setOffset(position.getOffset());
CPPASTFieldReference fieldRef = new CPPASTFieldReference(name, forInitExpr.copy());
IASTExpression expr= new CPPASTFunctionCallExpression(fieldRef, CPPVisitor.NO_ARGS);
expr.setParent(this);
expr.setPropertyInParent(ICPPASTRangeBasedForStatement.INITIALIZER);
CPPASTImplicitName begin= new CPPASTImplicitName(name.toCharArray(), this);
begin.setBinding(name.resolveBinding());
begin.setOffsetAndLength(position);
name = new CPPASTName(CPPVisitor.END);
name.setOffset(position.getOffset());
fieldRef.setFieldName(name);
CPPASTImplicitName end= new CPPASTImplicitName(name.toCharArray(), this);
end.setBinding(name.resolveBinding());
end.setOffsetAndLength(position);
fImplicitNames= new IASTImplicitName[] {begin, end};
}
}
}
if (fImplicitNames == null) {
CPPASTName name = new CPPASTName(CPPVisitor.BEGIN);
name.setOffset(position.getOffset());
CPPASTIdExpression fname = new CPPASTIdExpression(name);
IASTExpression expr= new CPPASTFunctionCallExpression(fname, new IASTInitializerClause[] {forInit.copy()});
expr.setParent(this);
expr.setPropertyInParent(ICPPASTRangeBasedForStatement.INITIALIZER);
CPPASTImplicitName begin= new CPPASTImplicitName(name.toCharArray(), this);
begin.setBinding(name.resolveBinding());
begin.setOffsetAndLength(position);
name = new CPPASTName(CPPVisitor.END);
name.setOffset(position.getOffset());
fname.setName(name);
CPPASTImplicitName end= new CPPASTImplicitName(name.toCharArray(), this);
end.setBinding(name.resolveBinding());
end.setOffsetAndLength(position);
fImplicitNames= new IASTImplicitName[] {begin, end};
}
}
return fImplicitNames;
}
@Override
public boolean accept( ASTVisitor action ){
if (action.shouldVisitStatements) {
@ -106,6 +186,14 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
return false;
if (fInitClause != null && !fInitClause.accept(action))
return false;
IASTImplicitName[] implicits = action.shouldVisitImplicitNames ? getImplicitNames() : null;
if (implicits != null) {
for (IASTImplicitName implicit : implicits) {
if (!implicit.accept(action))
return false;
}
}
if (fBody != null && !fBody.accept(action))
return false;
@ -114,6 +202,7 @@ public class CPPASTRangeBasedForStatement extends ASTNode implements ICPPASTRang
return true;
}
@Override
public void replace(IASTNode child, IASTNode other) {
if (child == fDeclaration) {
setDeclaration((IASTDeclaration) other);

View file

@ -649,23 +649,23 @@ public class CPPSemantics {
}
}
if (data.astName != null
&& CharArrayUtils.equals(CPPVisitor.BEGIN, data.astName.getSimpleID())) {
IASTNode parent = data.astName.getParent(); // id-expression
if (parent != null)
parent= parent.getParent(); // function call
if (parent != null)
parent= parent.getParent(); // the loop
if (parent != null)
parent= parent.getParent(); // unary *
if (parent instanceof ICPPASTRangeBasedForStatement) {
IBinding[] std= parent.getTranslationUnit().getScope().find(CPPVisitor.STD);
for (IBinding binding : std) {
if (binding instanceof ICPPNamespace) {
namespaces.add(((ICPPNamespace) binding).getNamespaceScope());
}
}
}
if (data.astName != null) {
final char[] simpleID = data.astName.getSimpleID();
if (CharArrayUtils.equals(CPPVisitor.BEGIN, simpleID) || CharArrayUtils.equals(CPPVisitor.END, simpleID)) {
IASTNode parent = data.astName.getParent(); // id-expression
if (parent != null)
parent= parent.getParent(); // function call
if (parent != null)
parent= parent.getParent(); // the loop
if (parent instanceof ICPPASTRangeBasedForStatement) {
IBinding[] std= parent.getTranslationUnit().getScope().find(CPPVisitor.STD);
for (IBinding binding : std) {
if (binding instanceof ICPPNamespace) {
namespaces.add(((ICPPNamespace) binding).getNamespaceScope());
}
}
}
}
}
return namespaces;
}

View file

@ -48,6 +48,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
@ -151,7 +152,6 @@ import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.ProblemType;
@ -201,14 +201,15 @@ public class CPPVisitor extends ASTQueries {
private static final CPPBasicType UNSIGNED_LONG = new CPPBasicType(Kind.eInt, IBasicType.IS_LONG | IBasicType.IS_UNSIGNED);
private static final CPPBasicType INT_TYPE = new CPPBasicType(Kind.eInt, 0);
private static final String BEGIN_STR = "begin"; //$NON-NLS-1$
static final char[] BEGIN = BEGIN_STR.toCharArray();
public static final String BEGIN_STR = "begin"; //$NON-NLS-1$
public static final char[] BEGIN = BEGIN_STR.toCharArray();
public static final char[] END = "end".toCharArray(); //$NON-NLS-1$
static final String STD = "std"; //$NON-NLS-1$
private static final char[] SIZE_T = "size_t".toCharArray(); //$NON-NLS-1$
private static final char[] PTRDIFF_T = "ptrdiff_t".toCharArray(); //$NON-NLS-1$
private static final char[] TYPE_INFO= "type_info".toCharArray(); //$NON-NLS-1$
private static final char[] INITIALIZER_LIST = "initializer_list".toCharArray(); //$NON-NLS-1$
private static final IASTInitializerClause[] NO_ARGS = {};
public static final IASTInitializerClause[] NO_ARGS = {};
// Thread-local set of DeclSpecifiers for which auto types are being created.
// Used to prevent infinite recursion while processing invalid self-referencing
@ -1925,22 +1926,23 @@ public class CPPVisitor extends ASTQueries {
IType type= SemanticUtil.getNestedType(expr.getExpressionType(), TDEF|CVTYPE);
if (type instanceof IArrayType) {
beginExpr= expr.copy();
} else if (type instanceof ICPPClassType) {
ICPPClassType ct= (ICPPClassType) type;
if (CPPSemantics.findBindings(ct.getCompositeScope(), BEGIN_STR, true).length > 0) {
final CPPASTName name = new CPPASTName(BEGIN);
name.setOffset(((ASTNode) forInit).getOffset());
beginExpr= new CPPASTFunctionCallExpression(
new CPPASTFieldReference(name, expr.copy()), NO_ARGS);
}
}
}
}
if (beginExpr == null) {
final CPPASTName name = new CPPASTName(BEGIN);
name.setOffset(((ASTNode) forInit).getOffset());
beginExpr= new CPPASTFunctionCallExpression(
new CPPASTIdExpression(name),
new IASTInitializerClause[] { forInit.copy() });
IASTImplicitName[] implicits= forStmt.getImplicitNames();
if (implicits.length > 0) {
IBinding b= implicits[0].getBinding();
CPPASTName name= new CPPASTName();
name.setBinding(b);
if (b instanceof ICPPMethod) {
beginExpr= new CPPASTFunctionCallExpression(
new CPPASTFieldReference(name, null), NO_ARGS);
} else {
beginExpr= new CPPASTFunctionCallExpression(new CPPASTIdExpression(name), NO_ARGS);
}
} else {
return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_AUTO_TYPE);
}
}
autoInitClause= new CPPASTUnaryExpression(IASTUnaryExpression.op_star, beginExpr);
autoInitClause.setParent(forStmt);