mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Fixed Bug 95411 incorrect parse of for statement
This commit is contained in:
parent
b453ede83c
commit
6597aae483
11 changed files with 98 additions and 218 deletions
|
@ -132,6 +132,27 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertSame(A, A_2);
|
||||
}
|
||||
|
||||
public void testBug95411() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( "class A {\n" );
|
||||
buffer.append( " public:" );
|
||||
buffer.append( "int x;" );
|
||||
buffer.append( "A * next;" );
|
||||
buffer.append( "};" );
|
||||
buffer.append( "A * start;" );
|
||||
buffer.append( "void test() {" );
|
||||
buffer.append( "for(A *y = start; y->x != 0; y = y->next) {" );
|
||||
buffer.append( "42;" );
|
||||
buffer.append( "}" );
|
||||
buffer.append( "for(int x = 0 ; x < 10; x++ ) {" );
|
||||
buffer.append( "}" );
|
||||
buffer.append( "}" );
|
||||
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
|
||||
CPPNameCollector nameCol = new CPPNameCollector();
|
||||
tu.accept( nameCol );
|
||||
assertNoProblemBindings( nameCol );
|
||||
}
|
||||
|
||||
public void testClassForwardDecl() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer("class A; class A {};"); //$NON-NLS-1$
|
||||
|
||||
|
|
|
@ -1024,9 +1024,9 @@ public class AST2Tests extends AST2BaseTest {
|
|||
// for(
|
||||
IASTForStatement for_stmt = (IASTForStatement) compound.getStatements()[0];
|
||||
// int i = 0;
|
||||
assertNull(for_stmt.getInitExpression());
|
||||
IASTSimpleDeclaration initDecl = (IASTSimpleDeclaration) for_stmt
|
||||
.getInitDeclaration();
|
||||
|
||||
IASTSimpleDeclaration initDecl = (IASTSimpleDeclaration) ((IASTDeclarationStatement) for_stmt
|
||||
.getInitializerStatement()).getDeclaration();
|
||||
IASTDeclarator dtor = initDecl.getDeclarators()[0];
|
||||
IASTName name_i = dtor.getName();
|
||||
// i < 5;
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
|
||||
|
@ -457,7 +458,7 @@ public class DOMLocationTests extends AST2BaseTest {
|
|||
: null) {
|
||||
IASTTranslationUnit tu = parse(code, p);
|
||||
IASTForStatement for_stmt = (IASTForStatement) ((IASTCompoundStatement)((IASTFunctionDefinition)tu.getDeclarations()[0]).getBody()).getStatements()[1];
|
||||
assertNull( for_stmt.getInitDeclaration() );
|
||||
assertTrue( for_stmt.getInitializerStatement() instanceof IASTNullStatement );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,22 +18,6 @@ package org.eclipse.cdt.core.dom.ast;
|
|||
*/
|
||||
public interface IASTForStatement extends IASTStatement {
|
||||
|
||||
/**
|
||||
* <code>INITEXPRESSION</code> represents the relationship between a
|
||||
* <code>IASTForStatement</code> and its <code>IASTExpression</code>
|
||||
* initializer.
|
||||
*/
|
||||
public static final ASTNodeProperty INITEXPRESSION = new ASTNodeProperty(
|
||||
"IASTForStatement.INITEXPRESSION - IASTExpression initializer for IASTForStatement"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* <code>INITDECLARATION</code> represents the relationship between a
|
||||
* <code>IASTForStatement</code> and its <code>IASTDeclaration</code>
|
||||
* initializer.
|
||||
*/
|
||||
public static final ASTNodeProperty INITDECLARATION = new ASTNodeProperty(
|
||||
"IASTForStatement.INITDECLARATION - IASTDeclaration initializer for IASTForStatement"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* <code>CONDITION</code> represents the relationship between a
|
||||
* <code>IASTForStatement</code> and its <code>IASTExpression</code>
|
||||
|
@ -58,36 +42,22 @@ public interface IASTForStatement extends IASTStatement {
|
|||
public static final ASTNodeProperty BODY = new ASTNodeProperty("IASTForStatement.BODY - IASTStatement body of IASTForStatement"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Get the initial expression for the loop. Returns null if there is none.
|
||||
* You can not have both an initial expression and an initial declaration.
|
||||
*
|
||||
* @return <code>IASTExpression</code>
|
||||
* <code>INITDECLARATION</code> represents the relationship between a
|
||||
* <code>IASTForStatement</code> and its <code>IASTDeclaration</code>
|
||||
* initializer.
|
||||
*/
|
||||
public IASTExpression getInitExpression();
|
||||
public static final ASTNodeProperty INITIALIZER = new ASTNodeProperty(
|
||||
"IASTForStatement.INITIALIZER - initializer for IASTForStatement"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Set the initial expression for the loop.
|
||||
*
|
||||
* @param expression
|
||||
* <code>IASTExpression</code>
|
||||
* @return
|
||||
*/
|
||||
public void setInit(IASTExpression expression);
|
||||
|
||||
public IASTStatement getInitializerStatement();
|
||||
/**
|
||||
* Get the initial declaration for the loop. Returns null if there is none.
|
||||
* You can not have both an initial declaration and an initial declaration.
|
||||
*
|
||||
* @return <code>IASTDeclaration</code>
|
||||
* @param statement
|
||||
*/
|
||||
public IASTDeclaration getInitDeclaration();
|
||||
public void setInitializerStatement( IASTStatement statement );
|
||||
|
||||
/**
|
||||
* Set the intiial declaration for the loop.
|
||||
*
|
||||
* @param declaration
|
||||
* <code>IASTDeclaration</code>
|
||||
*/
|
||||
public void setInit(IASTDeclaration declaration);
|
||||
|
||||
/**
|
||||
* Get the condition expression for the loop.
|
||||
|
|
|
@ -1450,8 +1450,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected abstract IASTDeclaration declaration() throws BacktrackException,
|
||||
EndOfFileException;
|
||||
|
||||
protected abstract IASTNode forInitStatement() throws BacktrackException,
|
||||
EndOfFileException;
|
||||
|
||||
|
||||
/**
|
||||
* @return
|
||||
|
@ -1826,7 +1825,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
int startOffset;
|
||||
startOffset = consume(IToken.t_for).getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTNode init = forInitStatement();
|
||||
IASTStatement init = forInitStatement();
|
||||
IASTExpression for_condition = null;
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
|
@ -1869,17 +1868,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
calculateEndOffset(for_body) - startOffset);
|
||||
}
|
||||
|
||||
if (init instanceof IASTDeclaration) {
|
||||
for_statement.setInit((IASTDeclaration) init);
|
||||
((IASTDeclaration) init).setParent(for_statement);
|
||||
((IASTDeclaration) init)
|
||||
.setPropertyInParent(IASTForStatement.INITDECLARATION);
|
||||
} else if (init instanceof IASTExpression) {
|
||||
for_statement.setInit((IASTExpression) init);
|
||||
((IASTExpression) init).setParent(for_statement);
|
||||
((IASTExpression) init)
|
||||
.setPropertyInParent(IASTForStatement.INITEXPRESSION);
|
||||
}
|
||||
for_statement.setInitializerStatement(init);
|
||||
init.setParent(for_statement);
|
||||
init.setPropertyInParent(IASTForStatement.INITIALIZER);
|
||||
|
||||
if (for_condition != null) {
|
||||
for_statement.setCondition(for_condition);
|
||||
for_condition.setParent(for_statement);
|
||||
|
@ -2187,4 +2179,16 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected abstract IASTDeclaration simpleDeclaration() throws BacktrackException,
|
||||
EndOfFileException;
|
||||
|
||||
/**
|
||||
* @throws BacktrackException
|
||||
*/
|
||||
protected IASTStatement forInitStatement() throws BacktrackException, EndOfFileException {
|
||||
if( LT(1) == IToken.tSEMI )
|
||||
return parseNullStatement();
|
||||
return parseDeclarationOrExpressionStatement();
|
||||
}
|
||||
|
||||
}
|
|
@ -10,7 +10,6 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
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.IASTForStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
|
@ -24,39 +23,10 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
|||
public class CASTForStatement extends CASTNode implements IASTForStatement, IASTAmbiguityParent {
|
||||
private IScope scope = null;
|
||||
|
||||
private IASTExpression initialExpression;
|
||||
private IASTDeclaration initDeclaration;
|
||||
private IASTExpression condition;
|
||||
private IASTExpression iterationExpression;
|
||||
private IASTStatement body;
|
||||
private IASTStatement body, init;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getInitExpression()
|
||||
*/
|
||||
public IASTExpression getInitExpression() {
|
||||
return initialExpression;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#setInit(org.eclipse.cdt.core.dom.ast.IASTExpression)
|
||||
*/
|
||||
public void setInit(IASTExpression expression) {
|
||||
this.initialExpression = expression;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getInitDeclaration()
|
||||
*/
|
||||
public IASTDeclaration getInitDeclaration() {
|
||||
return initDeclaration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#setInit(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
|
||||
*/
|
||||
public void setInit(IASTDeclaration declaration) {
|
||||
this.initDeclaration = declaration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getCondition()
|
||||
|
@ -118,8 +88,7 @@ public class CASTForStatement extends CASTNode implements IASTForStatement, IAST
|
|||
default : break;
|
||||
}
|
||||
}
|
||||
if( initDeclaration != null ) if( !initDeclaration.accept( action ) ) return false;
|
||||
if( initialExpression != null ) if( !initialExpression.accept( action ) ) return false;
|
||||
if( init != null ) if( !init.accept( action ) ) return false;
|
||||
if( condition != null ) if( !condition.accept( action ) ) return false;
|
||||
if( iterationExpression != null ) if( !iterationExpression.accept( action ) ) return false;
|
||||
if( body != null ) if( !body.accept( action ) ) return false;
|
||||
|
@ -133,11 +102,11 @@ public class CASTForStatement extends CASTNode implements IASTForStatement, IAST
|
|||
other.setParent( child.getParent() );
|
||||
body = (IASTStatement) other;
|
||||
}
|
||||
if( child == initialExpression )
|
||||
if( child == init )
|
||||
{
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
other.setParent( child.getParent() );
|
||||
initialExpression = (IASTExpression) other;
|
||||
init = (IASTStatement) other;
|
||||
}
|
||||
if( child == iterationExpression)
|
||||
{
|
||||
|
@ -154,4 +123,13 @@ public class CASTForStatement extends CASTNode implements IASTForStatement, IAST
|
|||
|
||||
}
|
||||
|
||||
public IASTStatement getInitializerStatement() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public void setInitializerStatement(IASTStatement statement) {
|
||||
init = statement;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1398,8 +1398,8 @@ public class CVisitor {
|
|||
return checkForBinding( scope, ((IASTDeclarationStatement)node).getDeclaration(), name, typesOnly, prefixMap );
|
||||
} else if( node instanceof IASTForStatement ){
|
||||
IASTForStatement forStatement = (IASTForStatement) node;
|
||||
if( forStatement.getInitDeclaration() != null ){
|
||||
return checkForBinding( scope, forStatement.getInitDeclaration(), name, typesOnly, prefixMap );
|
||||
if( forStatement.getInitializerStatement() instanceof IASTDeclarationStatement ){
|
||||
return checkForBinding( scope, ((IASTDeclarationStatement)forStatement.getInitializerStatement()).getDeclaration(), name, typesOnly, prefixMap );
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -53,7 +53,6 @@ import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
|
||||
|
@ -2266,44 +2265,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return new CASTParameterDeclaration();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws BacktrackException
|
||||
*/
|
||||
protected IASTNode forInitStatement() throws BacktrackException,
|
||||
EndOfFileException {
|
||||
IToken mark = mark();
|
||||
try {
|
||||
IASTExpression e = null;
|
||||
if( LT(1) != IToken.tSEMI )
|
||||
e = expression();
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
consume(IToken.tSEMI);
|
||||
break;
|
||||
case IToken.tEOC:
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
// TODO is this a problem? Should we wrap this in an expression
|
||||
// statement?
|
||||
return e;
|
||||
} catch (BacktrackException bt) {
|
||||
backup(mark);
|
||||
try {
|
||||
return simpleDeclaration();
|
||||
} catch (BacktrackException b) {
|
||||
IASTProblem p = failParse(b);
|
||||
IASTProblemExpression pe = createProblemExpression();
|
||||
((CASTNode) pe).setOffsetAndLength(((CASTNode) p));
|
||||
pe.setProblem(p);
|
||||
p.setParent(pe);
|
||||
p.setPropertyInParent(IASTProblemHolder.PROBLEM);
|
||||
return pe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
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.IASTForStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
|
@ -25,39 +24,9 @@ import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
|||
public class CPPASTForStatement extends CPPASTNode implements IASTForStatement, IASTAmbiguityParent {
|
||||
private IScope scope = null;
|
||||
|
||||
private IASTExpression initialExpression;
|
||||
private IASTDeclaration initDeclaration;
|
||||
private IASTExpression condition;
|
||||
private IASTExpression iterationExpression;
|
||||
private IASTStatement body;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getInitExpression()
|
||||
*/
|
||||
public IASTExpression getInitExpression() {
|
||||
return initialExpression;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#setInit(org.eclipse.cdt.core.dom.ast.IASTExpression)
|
||||
*/
|
||||
public void setInit(IASTExpression expression) {
|
||||
this.initialExpression = expression;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getInitDeclaration()
|
||||
*/
|
||||
public IASTDeclaration getInitDeclaration() {
|
||||
return initDeclaration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#setInit(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
|
||||
*/
|
||||
public void setInit(IASTDeclaration declaration) {
|
||||
this.initDeclaration = declaration;
|
||||
}
|
||||
private IASTStatement body, init;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTForStatement#getCondition()
|
||||
|
@ -119,8 +88,7 @@ public class CPPASTForStatement extends CPPASTNode implements IASTForStatement,
|
|||
default : break;
|
||||
}
|
||||
}
|
||||
if( initDeclaration != null ) if( !initDeclaration.accept( action ) ) return false;
|
||||
if( initialExpression != null ) if( !initialExpression.accept( action ) ) return false;
|
||||
if( init != null ) if( !init.accept( action ) ) return false;
|
||||
if( condition != null ) if( !condition.accept( action ) ) return false;
|
||||
if( iterationExpression != null ) if( !iterationExpression.accept( action ) ) return false;
|
||||
if( body != null ) if( !body.accept( action ) ) return false;
|
||||
|
@ -146,18 +114,19 @@ public class CPPASTForStatement extends CPPASTNode implements IASTForStatement,
|
|||
other.setParent( child.getParent() );
|
||||
iterationExpression = (IASTExpression) other;
|
||||
}
|
||||
if( child == initialExpression )
|
||||
if( child == init )
|
||||
{
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
other.setParent( child.getParent() );
|
||||
initialExpression = (IASTExpression) other;
|
||||
init = (IASTStatement) other;
|
||||
}
|
||||
if( initDeclaration == child )
|
||||
{
|
||||
other.setParent( child.getParent() );
|
||||
other.setPropertyInParent( child.getPropertyInParent() );
|
||||
initDeclaration = (IASTDeclaration) other;
|
||||
}
|
||||
|
||||
public IASTStatement getInitializerStatement() {
|
||||
return init;
|
||||
}
|
||||
|
||||
public void setInitializerStatement(IASTStatement statement) {
|
||||
init = statement;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1373,7 +1373,11 @@ public class CPPSemantics {
|
|||
else if( node instanceof IASTDeclarationStatement )
|
||||
declaration = ((IASTDeclarationStatement)node).getDeclaration();
|
||||
else if( node instanceof IASTForStatement && checkAux )
|
||||
declaration = ((IASTForStatement)node).getInitDeclaration();
|
||||
{
|
||||
if( ((IASTForStatement)node).getInitializerStatement() instanceof IASTDeclarationStatement )
|
||||
declaration = ((IASTDeclarationStatement)((IASTForStatement)node).getInitializerStatement()).getDeclaration();
|
||||
|
||||
}
|
||||
else if( node instanceof IASTParameterDeclaration ){
|
||||
IASTParameterDeclaration parameterDeclaration = (IASTParameterDeclaration) node;
|
||||
IASTDeclarator dtor = parameterDeclaration.getDeclarator();
|
||||
|
|
|
@ -4537,38 +4537,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return compoundStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws BacktrackException
|
||||
*/
|
||||
protected IASTNode forInitStatement() throws BacktrackException,
|
||||
EndOfFileException {
|
||||
IToken mark = mark();
|
||||
try {
|
||||
IASTExpression e = null;
|
||||
if (LT(1) != IToken.tSEMI)
|
||||
e = expression();
|
||||
switch (LT(1)) {
|
||||
case IToken.tSEMI:
|
||||
consume(IToken.tSEMI);
|
||||
break;
|
||||
case IToken.tEOC:
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
return e;
|
||||
} catch (BacktrackException bt) {
|
||||
backup(mark);
|
||||
try {
|
||||
return simpleDeclarationStrategyUnion();
|
||||
} catch (BacktrackException b) {
|
||||
failParse();
|
||||
throwBacktrack(b);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the top-level entry point into the ANSI C++ grammar.
|
||||
* translationUnit : (declaration)*
|
||||
|
@ -5335,4 +5303,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
--functionBodyCount;
|
||||
return s;
|
||||
}
|
||||
|
||||
protected IASTDeclaration simpleDeclaration() throws BacktrackException, EndOfFileException {
|
||||
return simpleDeclarationStrategyUnion();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue