diff options
author | Nathan Ridge | 2018-09-03 04:33:47 +0000 |
---|---|---|
committer | Nathan Ridge | 2018-09-11 03:22:26 +0000 |
commit | aeb6e386396abd763aa9bea7a3809c820e62c6e0 (patch) | |
tree | 5f782ddb5d73033fcb018bae89dce61acf1be503 | |
parent | 2f57d76a20f24b35db81862243662c26537037a8 (diff) | |
download | org.eclipse.cdt-aeb6e386396abd763aa9bea7a3809c820e62c6e0.tar.gz org.eclipse.cdt-aeb6e386396abd763aa9bea7a3809c820e62c6e0.tar.xz org.eclipse.cdt-aeb6e386396abd763aa9bea7a3809c820e62c6e0.zip |
Bug 538517 - Proper handling of range-for with temporary as range expression
Change-Id: I41c0ab58810c656d2ed89c9f5110ebc559e29575
2 files changed, 43 insertions, 1 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 39bc9c3fade..bbc12d656b1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -10191,6 +10191,23 @@ public class AST2CPPTests extends AST2CPPTestBase { public void testAutoTypeInRangeBasedFor_359653() throws Exception { parseAndCheckBindings(); } + + // struct Iter { + // Iter& operator++(); + // int& operator*(); + // friend bool operator!=(Iter, Iter); + // }; + // + // class C {}; + // Iter begin(C&); + // Iter end(C&); + // + // int main() { + // for (auto x : C()); // ERROR: Symbol 'begin' could not be resolved + // } + public void testRangedBasedFor_538517() throws Exception { + parseAndCheckImplicitNameBindings(); + } // typedef int T; // struct B { 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 1ea1cdfb9d4..5015394d195 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 @@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; @@ -49,6 +50,8 @@ public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implement private IASTStatement fBody; private IASTImplicitName[] fImplicitNames; private IASTImplicitDestructorName[] fImplicitDestructorNames; + + private static final char[] RANGE_EXPR = "__range".toCharArray(); //$NON-NLS-1$ public CPPASTRangeBasedForStatement() { } @@ -159,11 +162,33 @@ public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implement } } if (fImplicitNames == null) { + // Synthesize a notional '__range' variable to refer to the range expression. + // We can't use the range expression itself as the argument to begin() and + // end() because the range expression's value category might be a prvalue or + // xvalue, but the value category of the '__range' variable appearing in the + // notional rewrite specified in the standard is an lvalue. + CPPASTName rangeVarDeclName = new CPPASTName(RANGE_EXPR); + CPPVariable rangeVar = new CPPVariable(rangeVarDeclName); + CPPASTSimpleDeclSpecifier rangeVarDeclSpec = new CPPASTSimpleDeclSpecifier(); + rangeVarDeclSpec.setType(ICPPASTSimpleDeclSpecifier.t_auto); + CPPASTSimpleDeclaration rangeVarDecl = new CPPASTSimpleDeclaration(); + rangeVarDecl.setDeclSpecifier(rangeVarDeclSpec); + // Make the notional declaration of '__range_ a child of the range-for + // statement's body, so that name resolution in its initializer has + // a scope to work with. + rangeVarDecl.setParent(fBody); + CPPASTDeclarator rangeVarDeclarator = new CPPASTDeclarator(rangeVarDeclName); + rangeVarDeclarator.setInitializer(new CPPASTEqualsInitializer(forInit.copy())); + rangeVarDecl.addDeclarator(rangeVarDeclarator); + CPPASTName rangeVarRefName = new CPPASTName(RANGE_EXPR); + rangeVarRefName.setBinding(rangeVar); + CPPASTIdExpression rangeExpr = new CPPASTIdExpression(rangeVarRefName); + CPPASTName name = new CPPASTName(CPPVisitor.BEGIN); name.setOffset(position.getOffset()); CPPASTIdExpression fname = new CPPASTIdExpression(name); IASTExpression expr= new CPPASTFunctionCallExpression(fname, - new IASTInitializerClause[] { forInit.copy() }); + new IASTInitializerClause[] { rangeExpr }); expr.setParent(this); expr.setPropertyInParent(ICPPASTRangeBasedForStatement.INITIALIZER); |