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 7a16f8c56c7..b4d2d411973 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 @@ -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() ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTForStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTForStatement.java index 6c19d06fd3d..5f5a527575c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTForStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTForStatement.java @@ -42,8 +42,7 @@ public interface IASTForStatement extends IASTStatement { * * @return */ - public IASTDeclaration getInitDeclaration(); - + public IASTDeclaration getInitDeclaration(); public void setInit(IASTDeclaration declaration); /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTWhileStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTWhileStatement.java index 28fbf06edc4..9bfe98b3996 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTWhileStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTWhileStatement.java @@ -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); /** diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTWhileStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTWhileStatement.java new file mode 100644 index 00000000000..f24d25ebc2b --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTWhileStatement.java @@ -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); + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index 9990f37e609..3fed249477a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java index aa87da494cc..f5d690196f6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTWhileStatement.java @@ -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; + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index d1060f8a458..09c37f9f30e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -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 ) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index d7a2e7a781d..c61eb956ff2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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; + } + } +} + } \ No newline at end of file