1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-30 20:35:38 +02:00

Bug 538517 - Proper handling of range-for with temporary as range expression

Change-Id: I41c0ab58810c656d2ed89c9f5110ebc559e29575
This commit is contained in:
Nathan Ridge 2018-09-03 00:33:47 -04:00
parent 2f57d76a20
commit aeb6e38639
2 changed files with 43 additions and 1 deletions

View file

@ -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 {

View file

@ -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);