From 545ae7e7f93755193100fad2995449e80573776b Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Thu, 5 Jan 2012 11:21:02 +0100 Subject: [PATCH] Bug 367611: Implicit names for begin() and end() in range based for loop. --- .../cpp/ICPPASTRangeBasedForStatement.java | 5 +- .../cpp/CPPASTRangeBasedForStatement.java | 99 ++++++++++++++++++- .../parser/cpp/semantics/CPPSemantics.java | 34 +++---- .../dom/parser/cpp/semantics/CPPVisitor.java | 38 +++---- 4 files changed, 135 insertions(+), 41 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTRangeBasedForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTRangeBasedForStatement.java index 1168b97c022..7a47c036c27 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTRangeBasedForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTRangeBasedForStatement.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java index 49c84b0bbfa..f7e353d70b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 66990204aa2..fde5e727d38 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index bb05ecc1157..e97fe4f13e1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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);