mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Fixed Bugzilla Bug 84478 - [C++ Parser] does not support declarations inside while condition
This commit is contained in:
parent
c0d9fbb554
commit
14feb82cc2
8 changed files with 135 additions and 15 deletions
|
@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.IVariable;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
|
@ -2190,5 +2191,25 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertInstances( col, j, 3 );
|
||||
assertInstances( col, x, 5 );
|
||||
}
|
||||
|
||||
public void testBug84478() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( "void foo() {\n" ); //$NON-NLS-1$
|
||||
buffer.append( " struct A {\n" ); //$NON-NLS-1$
|
||||
buffer.append( " int val;\n" ); //$NON-NLS-1$
|
||||
buffer.append( " A(int i) : val(i) { }\n" ); //$NON-NLS-1$
|
||||
buffer.append( " ~A() { }\n" ); //$NON-NLS-1$
|
||||
buffer.append( " operator bool() { return val != 0; }\n" ); //$NON-NLS-1$
|
||||
buffer.append( " };\n" ); //$NON-NLS-1$
|
||||
buffer.append( " int i = 1;\n" ); //$NON-NLS-1$
|
||||
buffer.append( " while (A a = i) {\n" ); //$NON-NLS-1$
|
||||
buffer.append( " i = 0;\n" ); //$NON-NLS-1$
|
||||
buffer.append( " }\n" ); //$NON-NLS-1$
|
||||
buffer.append( "}\n" ); //$NON-NLS-1$
|
||||
IASTFunctionDefinition foo = (IASTFunctionDefinition) parse( buffer.toString(), ParserLanguage.CPP ).getDeclarations()[0];
|
||||
ICPPASTWhileStatement whileStatement = (ICPPASTWhileStatement) ((IASTCompoundStatement)foo.getBody()).getStatements()[2];
|
||||
assertNull( whileStatement.getCondition() );
|
||||
assertNotNull( whileStatement.getConditionDeclaration() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,7 @@ public interface IASTForStatement extends IASTStatement {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public IASTDeclaration getInitDeclaration();
|
||||
|
||||
public IASTDeclaration getInitDeclaration();
|
||||
public void setInit(IASTDeclaration declaration);
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,7 @@ package org.eclipse.cdt.core.dom.ast;
|
|||
*/
|
||||
public interface IASTWhileStatement extends IASTStatement {
|
||||
|
||||
public static final ASTNodeProperty CONDITION = new ASTNodeProperty("condition"); //$NON-NLS-1$
|
||||
public static final ASTNodeProperty CONDITIONEXPRESSION = new ASTNodeProperty("condition"); //$NON-NLS-1$
|
||||
public static final ASTNodeProperty BODY = new ASTNodeProperty("body"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,6 @@ public interface IASTWhileStatement extends IASTStatement {
|
|||
* @return expression for the condition
|
||||
*/
|
||||
public IASTExpression getCondition();
|
||||
|
||||
public void setCondition(IASTExpression condition);
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2004 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
**********************************************************************/
|
||||
package org.eclipse.cdt.core.dom.ast.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
*
|
||||
*/
|
||||
public interface ICPPASTWhileStatement extends IASTWhileStatement {
|
||||
|
||||
public static final ASTNodeProperty CONDITIONDECLARATION = new ASTNodeProperty("initDeclaration"); //$NON-NLS-1$
|
||||
public IASTDeclaration getConditionDeclaration();
|
||||
public void setConditionDeclaration(IASTDeclaration declaration);
|
||||
|
||||
}
|
|
@ -1276,7 +1276,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected IASTExpression condition() throws BacktrackException,
|
||||
EndOfFileException {
|
||||
IASTExpression cond = expression();
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
|
@ -1776,8 +1775,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
*/
|
||||
protected IASTStatement parseWhileStatement() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
int startOffset;
|
||||
startOffset = consume(IToken.t_while).getOffset();
|
||||
int startOffset = consume(IToken.t_while).getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTExpression while_condition = condition();
|
||||
consume(IToken.tRPAREN);
|
||||
|
@ -1788,7 +1786,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
calculateEndOffset(while_body) - startOffset);
|
||||
while_statement.setCondition(while_condition);
|
||||
while_condition.setParent(while_statement);
|
||||
while_condition.setPropertyInParent(IASTWhileStatement.CONDITION);
|
||||
while_condition.setPropertyInParent(IASTWhileStatement.CONDITIONEXPRESSION);
|
||||
while_statement.setBody(while_body);
|
||||
while_condition.setParent(while_statement);
|
||||
while_condition.setPropertyInParent(IASTWhileStatement.BODY);
|
||||
|
|
|
@ -10,17 +10,19 @@
|
|||
**********************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
*/
|
||||
public class CPPASTWhileStatement extends CPPASTNode implements
|
||||
IASTWhileStatement {
|
||||
ICPPASTWhileStatement {
|
||||
private IASTExpression condition;
|
||||
private IASTStatement body;
|
||||
private IASTDeclaration condition2;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IASTWhileStatement#getCondition()
|
||||
|
@ -50,4 +52,18 @@ public class CPPASTWhileStatement extends CPPASTNode implements
|
|||
this.body = body;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement#getInitDeclaration()
|
||||
*/
|
||||
public IASTDeclaration getConditionDeclaration() {
|
||||
return condition2;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement#setInit(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
|
||||
*/
|
||||
public void setConditionDeclaration(IASTDeclaration declaration) {
|
||||
condition2 = declaration;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTypenameExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||
|
@ -1275,8 +1276,14 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
if( !visitExpression( ((IASTSwitchStatement) statement ).getController(), action ) ) return false;
|
||||
if( !visitStatement( ((IASTSwitchStatement) statement ).getBody(), action ) ) return false;
|
||||
} else if( statement instanceof IASTWhileStatement ){
|
||||
if( !visitExpression( ((IASTWhileStatement) statement ).getCondition(), action ) ) return false;
|
||||
if( !visitStatement( ((IASTWhileStatement) statement ).getBody(), action ) ) return false;
|
||||
IASTWhileStatement whileStatement = (IASTWhileStatement) statement;
|
||||
if( whileStatement.getCondition() != null && !visitExpression( (whileStatement ).getCondition(), action ) ) return false;
|
||||
if( !visitStatement( (whileStatement ).getBody(), action ) ) return false;
|
||||
if( whileStatement instanceof ICPPASTWhileStatement )
|
||||
{
|
||||
ICPPASTWhileStatement cppWhile = ((ICPPASTWhileStatement)whileStatement);
|
||||
if ( cppWhile.getConditionDeclaration() != null && !visitDeclaration( cppWhile.getConditionDeclaration(), action ) ) return false;
|
||||
}
|
||||
} else if( statement instanceof IASTForStatement ){
|
||||
IASTForStatement s = (IASTForStatement) statement;
|
||||
if( s.getInitDeclaration() != null )
|
||||
|
|
|
@ -114,6 +114,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisiblityLabel;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
|
||||
|
@ -4310,8 +4311,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if( LT(1) != IToken.tSEMI )
|
||||
e = expression();
|
||||
consume(IToken.tSEMI);
|
||||
// TODO is this a problem? Should we wrap this in an expression
|
||||
// statement?
|
||||
return e;
|
||||
} catch (BacktrackException bt) {
|
||||
backup(mark);
|
||||
|
@ -4323,7 +4322,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4848,4 +4846,59 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
.resolveOtherAmbiguitiesAsDeclaration(ds, expressionStatement);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser#parseWhileStatement()
|
||||
*/
|
||||
protected IASTStatement parseWhileStatement() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
int startOffset = consume(IToken.t_while).getOffset();
|
||||
consume(IToken.tLPAREN);
|
||||
IASTNode while_condition = whileCondition();
|
||||
consume(IToken.tRPAREN);
|
||||
IASTStatement while_body = statement();
|
||||
|
||||
ICPPASTWhileStatement while_statement = (ICPPASTWhileStatement) createWhileStatement();
|
||||
((ASTNode) while_statement).setOffsetAndLength(startOffset,
|
||||
calculateEndOffset(while_body) - startOffset);
|
||||
if( while_condition instanceof IASTExpression )
|
||||
{
|
||||
while_statement.setCondition((IASTExpression)while_condition);
|
||||
while_condition.setParent(while_statement);
|
||||
while_condition.setPropertyInParent(IASTWhileStatement.CONDITIONEXPRESSION);
|
||||
}
|
||||
else if ( while_condition instanceof IASTDeclaration )
|
||||
{
|
||||
while_statement.setConditionDeclaration((IASTDeclaration) while_condition);
|
||||
while_condition.setParent(while_statement);
|
||||
while_condition.setPropertyInParent(ICPPASTWhileStatement.CONDITIONDECLARATION);
|
||||
}
|
||||
while_statement.setBody(while_body);
|
||||
while_body.setParent(while_statement);
|
||||
while_body.setPropertyInParent(IASTWhileStatement.BODY);
|
||||
return while_statement;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
protected IASTNode whileCondition() throws BacktrackException, EndOfFileException {
|
||||
IToken mark = mark();
|
||||
try {
|
||||
IASTExpression e = expression();
|
||||
if( LT(1) != IToken.tRPAREN )
|
||||
throwBacktrack(LA(1));
|
||||
return e;
|
||||
} catch (BacktrackException bt) {
|
||||
backup(mark);
|
||||
try {
|
||||
return simpleDeclaration( SimpleDeclarationStrategy.TRY_VARIABLE, true );
|
||||
} catch (BacktrackException b) {
|
||||
failParse();
|
||||
throwBacktrack(b);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue