mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-05 15:25:49 +02:00
Bug 538517 - Proper handling of range-for with temporary as range expression
Change-Id: I41c0ab58810c656d2ed89c9f5110ebc559e29575
This commit is contained in:
parent
2f57d76a20
commit
aeb6e38639
2 changed files with 43 additions and 1 deletions
|
@ -10192,6 +10192,23 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
||||||
parseAndCheckBindings();
|
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;
|
// typedef int T;
|
||||||
// struct B {
|
// struct B {
|
||||||
// int a, b;
|
// int a, b;
|
||||||
|
|
|
@ -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.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
|
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.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.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
@ -50,6 +51,8 @@ public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implement
|
||||||
private IASTImplicitName[] fImplicitNames;
|
private IASTImplicitName[] fImplicitNames;
|
||||||
private IASTImplicitDestructorName[] fImplicitDestructorNames;
|
private IASTImplicitDestructorName[] fImplicitDestructorNames;
|
||||||
|
|
||||||
|
private static final char[] RANGE_EXPR = "__range".toCharArray(); //$NON-NLS-1$
|
||||||
|
|
||||||
public CPPASTRangeBasedForStatement() {
|
public CPPASTRangeBasedForStatement() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +162,33 @@ public class CPPASTRangeBasedForStatement extends CPPASTAttributeOwner implement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fImplicitNames == null) {
|
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);
|
CPPASTName name = new CPPASTName(CPPVisitor.BEGIN);
|
||||||
name.setOffset(position.getOffset());
|
name.setOffset(position.getOffset());
|
||||||
CPPASTIdExpression fname = new CPPASTIdExpression(name);
|
CPPASTIdExpression fname = new CPPASTIdExpression(name);
|
||||||
IASTExpression expr= new CPPASTFunctionCallExpression(fname,
|
IASTExpression expr= new CPPASTFunctionCallExpression(fname,
|
||||||
new IASTInitializerClause[] { forInit.copy() });
|
new IASTInitializerClause[] { rangeExpr });
|
||||||
expr.setParent(this);
|
expr.setParent(this);
|
||||||
expr.setPropertyInParent(ICPPASTRangeBasedForStatement.INITIALIZER);
|
expr.setPropertyInParent(ICPPASTRangeBasedForStatement.INITIALIZER);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue