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

Ambiguity handling for c++ conditions, bug 263158.

This commit is contained in:
Markus Schorn 2009-02-03 12:14:36 +00:00
parent c97571595e
commit 155e36d7b3
9 changed files with 236 additions and 127 deletions

View file

@ -6617,16 +6617,26 @@ public class AST2CPPTests extends AST2BaseTest {
}
// struct A {};
//
// void test() {
// while (
// A* a = 0
// );
// int B, b;
// while (A* a = 0);
// while (A* a = 0) {a= 0;}
// while (B* b) {b= 0;}
// if (A* a = 0) {a= 0;}
// if (B* b) {b= 0;}
// switch (A* a = 0) {case 1: a=0;}
// switch (B* b) {case1: b= 0;}
// for (;A* a = 0;) {a= 0;}
// for (;B* b;) {b= 0;}
// }
public void _testAmbiguityResolutionInCondition_263158() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
public void testAmbiguityResolutionInCondition_263158() throws Exception {
final String code = getAboveComment();
BindingAssertionHelper ba= new BindingAssertionHelper(code, true);
ba.assertNonProblem("A*", 1, ICPPClassType.class);
ba.assertNonProblem("a", 1, ICPPVariable.class);
ba.assertNonProblem("B*", 1, ICPPVariable.class);
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// void f(int x);

View file

@ -76,7 +76,9 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
}
} else if (node instanceof IASTDeclarationStatement) {
repopulateScope(((IASTDeclarationStatement) node).getDeclaration());
}
} else if (node instanceof IASTDeclaration) {
repopulateScope((IASTDeclaration) node);
}
return PROCESS_SKIP;
}

View file

@ -0,0 +1,60 @@
/*******************************************************************************
* Copyright (c) 2009 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
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.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
/**
* Handles ambiguity between expression and declaration in a condition.
*/
public class CPPASTAmbiguousCondition extends ASTAmbiguousNode implements IASTAmbiguousCondition {
private IASTExpression fExpression;
private IASTDeclaration fDeclaration;
public CPPASTAmbiguousCondition(IASTExpression expression, IASTSimpleDeclaration declaration) {
fExpression= expression;
fDeclaration= declaration;
expression.setParent(this);
expression.setPropertyInParent(SUBCONDITION);
declaration.setParent(this);
declaration.setPropertyInParent(SUBCONDITION);
}
@Override
public IASTNode[] getNodes() {
return new IASTNode[] {fExpression, fDeclaration};
}
@Override
protected void beforeResolution() {
// populate containing scope, so that it will not be affected by the alternative branches.
IScope scope= CPPVisitor.getContainingScope(this);
if (scope instanceof ICPPASTInternalScope) {
((ICPPASTInternalScope) scope).populateCache();
}
}
public IASTExpression copy() {
throw new UnsupportedOperationException();
}
public IType getExpressionType() {
return null;
}
}

View file

@ -1,13 +1,14 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* Emanuel Graf IFS - Bugfix for #198269
* John Camelon (IBM) - Initial API and implementation
* Emanuel Graf IFS - Bug 198269
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -22,16 +23,17 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
* For statement in c++
*/
public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement, IASTAmbiguityParent {
private IScope scope = null;
private IASTStatement init;
private IASTExpression condition;
private IASTExpression iterationExpression;
private IASTStatement body, init;
private IASTDeclaration condDeclaration;
private IASTExpression iterationExpression;
private IASTStatement body;
public CPPASTForStatement() {
@ -74,6 +76,7 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
if (condition != null) {
condition.setParent(this);
condition.setPropertyInParent(CONDITION);
condDeclaration= null;
}
}
@ -134,39 +137,27 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
return true;
}
public void replace(IASTNode child, IASTNode other) {
if( body == child )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
body = (IASTStatement) other;
}
if( child == condition )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
condition = (IASTExpression) other;
}
if( child == condDeclaration )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
condDeclaration = (IASTDeclaration) other;
}
if( child == iterationExpression )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
iterationExpression = (IASTExpression) other;
}
if( child == init )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
init = (IASTStatement) other;
}
}
public void replace(IASTNode child, IASTNode other) {
if (body == child) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
body = (IASTStatement) other;
} else if (child == condition || child == condDeclaration) {
if (other instanceof IASTExpression) {
setConditionExpression((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setConditionDeclaration((IASTDeclaration) other);
}
} else if (child == iterationExpression) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
iterationExpression = (IASTExpression) other;
} else if (child == init) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
init = (IASTStatement) other;
}
}
public IASTStatement getInitializerStatement() {
return init;
@ -187,6 +178,7 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
if (d != null) {
d.setParent(this);
d.setPropertyInParent(CONDITION_DECLARATION);
condition= null;
}
}

View file

@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -21,7 +21,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
* If statement in c++
*/
public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IASTAmbiguityParent {
@ -68,6 +68,7 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
if (condition != null) {
condition.setParent(this);
condition.setPropertyInParent(CONDITION);
condDecl= null;
}
}
@ -122,7 +123,7 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
return true;
}
public void replace(IASTNode child, IASTNode other) {
public void replace(IASTNode child, IASTNode other) {
if (thenClause == child) {
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
@ -131,14 +132,12 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
elseClause = (IASTStatement) other;
} else if (condDecl == child) {
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
condDecl = (IASTDeclaration) other;
} else if (condition == child) {
other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent());
condition = (IASTExpression) other;
} else if (condition == child || condDecl == child) {
if (other instanceof IASTExpression) {
setConditionExpression((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setConditionDeclaration((IASTDeclaration) other);
}
}
}
@ -152,6 +151,7 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
if (d != null) {
d.setParent(this);
d.setPropertyInParent(CONDITION);
condition= null;
}
}

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -21,15 +22,15 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
* Switch statement in c++.
*/
public class CPPASTSwitchStatement extends ASTNode implements
ICPPASTSwitchStatement, IASTAmbiguityParent {
private IScope scope;
private IASTExpression controller;
private IASTExpression controllerExpression;
private IASTDeclaration controllerDeclaration;
private IASTStatement body;
private IASTDeclaration decl;
public CPPASTSwitchStatement() {
@ -47,23 +48,24 @@ public class CPPASTSwitchStatement extends ASTNode implements
public CPPASTSwitchStatement copy() {
CPPASTSwitchStatement copy = new CPPASTSwitchStatement();
copy.setControllerDeclaration(decl == null ? null : decl.copy());
copy.setControllerExpression(controller == null ? null : controller.copy());
copy.setControllerDeclaration(controllerDeclaration == null ? null : controllerDeclaration.copy());
copy.setControllerExpression(controllerExpression == null ? null : controllerExpression.copy());
copy.setBody(body == null ? null : body.copy());
copy.setOffsetAndLength(this);
return copy;
}
public IASTExpression getControllerExpression() {
return controller;
return controllerExpression;
}
public void setControllerExpression(IASTExpression controller) {
assertNotFrozen();
this.controller = controller;
this.controllerExpression = controller;
if (controller != null) {
controller.setParent(this);
controller.setPropertyInParent(CONTROLLER_EXP);
controllerDeclaration= null;
}
}
@ -89,8 +91,8 @@ public class CPPASTSwitchStatement extends ASTNode implements
default : break;
}
}
if( controller != null ) if( !controller.accept( action ) ) return false;
if( decl != null ) if( !decl.accept( action ) ) return false;
if( controllerExpression != null ) if( !controllerExpression.accept( action ) ) return false;
if( controllerDeclaration != null ) if( !controllerDeclaration.accept( action ) ) return false;
if( body != null ) if( !body.accept( action ) ) return false;
if( action.shouldVisitStatements ){
@ -104,37 +106,30 @@ public class CPPASTSwitchStatement extends ASTNode implements
}
public void replace(IASTNode child, IASTNode other) {
if( body == child )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
body = (IASTStatement) other;
}
if( child == controller )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
controller = (IASTExpression) other;
}
if( child == decl )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
decl = (IASTDeclaration) other;
}
}
if (body == child) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
body = (IASTStatement) other;
} else if (controllerDeclaration == child || controllerExpression == child) {
if (other instanceof IASTExpression) {
setControllerExpression((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setControllerDeclaration((IASTDeclaration) other);
}
}
}
public IASTDeclaration getControllerDeclaration() {
return decl;
return controllerDeclaration;
}
public void setControllerDeclaration(IASTDeclaration d) {
assertNotFrozen();
decl = d;
controllerDeclaration = d;
if (d != null) {
d.setParent(this);
d.setPropertyInParent(CONTROLLER_DECLARATION);
controllerExpression= null;
}
}

View file

@ -1,12 +1,13 @@
/*******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* Copyright (c) 2004, 2009 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
@ -21,7 +22,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
* While statement in c++.
*/
public class CPPASTWhileStatement extends ASTNode implements
ICPPASTWhileStatement, IASTAmbiguityParent {
@ -63,6 +64,7 @@ public class CPPASTWhileStatement extends ASTNode implements
if (condition != null) {
condition.setParent(this);
condition.setPropertyInParent(CONDITIONEXPRESSION);
condition2= null;
}
}
@ -89,6 +91,7 @@ public class CPPASTWhileStatement extends ASTNode implements
if (declaration != null) {
declaration.setParent(this);
declaration.setPropertyInParent(CONDITIONDECLARATION);
condition= null;
}
}
@ -115,26 +118,20 @@ public class CPPASTWhileStatement extends ASTNode implements
return true;
}
public void replace(IASTNode child, IASTNode other) {
if( body == child )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
body = (IASTStatement) other;
}
if( child == condition )
{
other.setPropertyInParent( child.getPropertyInParent() );
other.setParent( child.getParent() );
condition = (IASTExpression) other;
}
if( condition2 == child )
{
other.setParent( child.getParent() );
other.setPropertyInParent( child.getPropertyInParent() );
condition2 = (IASTDeclaration) other;
}
}
public void replace(IASTNode child, IASTNode other) {
if (body == child) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
body = (IASTStatement) other;
}
if (child == condition || child == condition2) {
if (other instanceof IASTExpression) {
setCondition((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setConditionDeclaration((IASTDeclaration) other);
}
}
}
public IScope getScope() {
if( scope == null )

View file

@ -3669,25 +3669,56 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
protected IASTNode cppStyleCondition(int expectToken) throws BacktrackException, EndOfFileException {
IASTExpression e= null;
IASTSimpleDeclaration decl= null;
IToken end= null;
IToken mark = mark();
try {
IASTExpression e = expression();
final int lt1= LT(1);
if (lt1 == expectToken || lt1 == IToken.tEOC) {
return e;
}
} catch (BacktrackException bt) {
decl= simpleSingleDeclaration(DeclarationOptions.CONDITION);
end= LA(1);
final int la= end.getType();
if (la != expectToken && la != IToken.tEOC) {
end= null;
decl= null;
}
} catch (BacktrackException b) {
}
backup(mark);
try {
return simpleSingleDeclaration(DeclarationOptions.CONDITION);
} catch (BacktrackException b) {
if (expectToken == IToken.tRPAREN) {
backup(mark);
return skipProblemConditionInParenthesis(mark.getOffset());
e= expression();
final IToken end2= LA(1);
final int la= end2.getType();
if (la != expectToken && la != IToken.tEOC) {
throwBacktrack(end2);
}
if (end == null)
return e;
final int endOffset = end.getOffset();
final int endOffset2 = end2.getOffset();
if (endOffset == endOffset2) {
CPPASTAmbiguousCondition ambig= new CPPASTAmbiguousCondition(e, decl);
setRange(ambig, e);
return ambig;
}
if (endOffset < endOffset2)
return e;
} catch (BacktrackException bt) {
if (end == null) {
if (expectToken == IToken.tRPAREN) {
backup(mark);
return skipProblemConditionInParenthesis(mark.getOffset());
}
throw bt;
}
throw b;
}
backup(end);
return decl;
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2009 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
/**
* Marks ambiguous condition nodes.
*/
public interface IASTAmbiguousCondition extends IASTExpression {
public static final ASTNodeProperty SUBCONDITION = new ASTNodeProperty( "IASTAmbiguousCondition.SUBCONDITION"); //$NON-NLS-1$
}