summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2018-09-03 00:33:47 -0400
committerNathan Ridge2018-09-10 23:22:26 -0400
commitaeb6e386396abd763aa9bea7a3809c820e62c6e0 (patch)
tree5f782ddb5d73033fcb018bae89dce61acf1be503
parent2f57d76a20f24b35db81862243662c26537037a8 (diff)
downloadorg.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
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java17
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTRangeBasedForStatement.java27
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 39bc9c3fad..bbc12d656b 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 1ea1cdfb9d..5015394d19 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);