1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-01 13:25:45 +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 {}; // struct A {};
//
// void test() { // void test() {
// while ( // int B, b;
// A* a = 0 // 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 { public void testAmbiguityResolutionInCondition_263158() throws Exception {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); final String code = getAboveComment();
BindingAssertionHelper ba= new BindingAssertionHelper(code, true);
ba.assertNonProblem("A*", 1, ICPPClassType.class); ba.assertNonProblem("A*", 1, ICPPClassType.class);
ba.assertNonProblem("a", 1, ICPPVariable.class); ba.assertNonProblem("a", 1, ICPPVariable.class);
ba.assertNonProblem("B*", 1, ICPPVariable.class);
parseAndCheckBindings(code, ParserLanguage.CPP);
} }
// void f(int x); // void f(int x);

View file

@ -76,6 +76,8 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
} }
} else if (node instanceof IASTDeclarationStatement) { } else if (node instanceof IASTDeclarationStatement) {
repopulateScope(((IASTDeclarationStatement) node).getDeclaration()); repopulateScope(((IASTDeclarationStatement) node).getDeclaration());
} else if (node instanceof IASTDeclaration) {
repopulateScope((IASTDeclaration) node);
} }
return PROCESS_SKIP; 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* IBM - Initial API and implementation * John Camelon (IBM) - Initial API and implementation
* Emanuel Graf IFS - Bugfix for #198269 * Emanuel Graf IFS - Bug 198269
* Markus Schorn (Wind River Systems)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/** /**
* @author jcamelon * For statement in c++
*/ */
public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement, IASTAmbiguityParent { public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement, IASTAmbiguityParent {
private IScope scope = null; private IScope scope = null;
private IASTStatement init;
private IASTExpression condition; private IASTExpression condition;
private IASTExpression iterationExpression;
private IASTStatement body, init;
private IASTDeclaration condDeclaration; private IASTDeclaration condDeclaration;
private IASTExpression iterationExpression;
private IASTStatement body;
public CPPASTForStatement() { public CPPASTForStatement() {
@ -74,6 +76,7 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
if (condition != null) { if (condition != null) {
condition.setParent(this); condition.setParent(this);
condition.setPropertyInParent(CONDITION); condition.setPropertyInParent(CONDITION);
condDeclaration= null;
} }
} }
@ -135,33 +138,21 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
} }
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
if( body == child ) if (body == child) {
{
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
body = (IASTStatement) other; body = (IASTStatement) other;
} else if (child == condition || child == condDeclaration) {
if (other instanceof IASTExpression) {
setConditionExpression((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setConditionDeclaration((IASTDeclaration) other);
} }
if( child == condition ) } else if (child == iterationExpression) {
{
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.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
iterationExpression = (IASTExpression) other; iterationExpression = (IASTExpression) other;
} } else if (child == init) {
if( child == init )
{
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
init = (IASTStatement) other; init = (IASTStatement) other;
@ -187,6 +178,7 @@ public class CPPASTForStatement extends ASTNode implements ICPPASTForStatement,
if (d != null) { if (d != null) {
d.setParent(this); d.setParent(this);
d.setPropertyInParent(CONDITION_DECLARATION); 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* IBM - Initial API and implementation * John Camelon (IBM) - Initial API and implementation
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/** /**
* @author jcamelon * If statement in c++
*/ */
public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IASTAmbiguityParent { public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IASTAmbiguityParent {
@ -68,6 +68,7 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
if (condition != null) { if (condition != null) {
condition.setParent(this); condition.setParent(this);
condition.setPropertyInParent(CONDITION); condition.setPropertyInParent(CONDITION);
condDecl= null;
} }
} }
@ -131,14 +132,12 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
other.setParent(child.getParent()); other.setParent(child.getParent());
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
elseClause = (IASTStatement) other; elseClause = (IASTStatement) other;
} else if (condDecl == child) { } else if (condition == child || condDecl == child) {
other.setParent(child.getParent()); if (other instanceof IASTExpression) {
other.setPropertyInParent(child.getPropertyInParent()); setConditionExpression((IASTExpression) other);
condDecl = (IASTDeclaration) other; } else if (other instanceof IASTDeclaration) {
} else if (condition == child) { setConditionDeclaration((IASTDeclaration) other);
other.setParent(child.getParent()); }
other.setPropertyInParent(child.getPropertyInParent());
condition = (IASTExpression) other;
} }
} }
@ -152,6 +151,7 @@ public class CPPASTIfStatement extends ASTNode implements ICPPASTIfStatement, IA
if (d != null) { if (d != null) {
d.setParent(this); d.setParent(this);
d.setPropertyInParent(CONDITION); 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * 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; 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; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/** /**
* @author jcamelon * Switch statement in c++.
*/ */
public class CPPASTSwitchStatement extends ASTNode implements public class CPPASTSwitchStatement extends ASTNode implements
ICPPASTSwitchStatement, IASTAmbiguityParent { ICPPASTSwitchStatement, IASTAmbiguityParent {
private IScope scope; private IScope scope;
private IASTExpression controller; private IASTExpression controllerExpression;
private IASTDeclaration controllerDeclaration;
private IASTStatement body; private IASTStatement body;
private IASTDeclaration decl;
public CPPASTSwitchStatement() { public CPPASTSwitchStatement() {
@ -47,23 +48,24 @@ public class CPPASTSwitchStatement extends ASTNode implements
public CPPASTSwitchStatement copy() { public CPPASTSwitchStatement copy() {
CPPASTSwitchStatement copy = new CPPASTSwitchStatement(); CPPASTSwitchStatement copy = new CPPASTSwitchStatement();
copy.setControllerDeclaration(decl == null ? null : decl.copy()); copy.setControllerDeclaration(controllerDeclaration == null ? null : controllerDeclaration.copy());
copy.setControllerExpression(controller == null ? null : controller.copy()); copy.setControllerExpression(controllerExpression == null ? null : controllerExpression.copy());
copy.setBody(body == null ? null : body.copy()); copy.setBody(body == null ? null : body.copy());
copy.setOffsetAndLength(this); copy.setOffsetAndLength(this);
return copy; return copy;
} }
public IASTExpression getControllerExpression() { public IASTExpression getControllerExpression() {
return controller; return controllerExpression;
} }
public void setControllerExpression(IASTExpression controller) { public void setControllerExpression(IASTExpression controller) {
assertNotFrozen(); assertNotFrozen();
this.controller = controller; this.controllerExpression = controller;
if (controller != null) { if (controller != null) {
controller.setParent(this); controller.setParent(this);
controller.setPropertyInParent(CONTROLLER_EXP); controller.setPropertyInParent(CONTROLLER_EXP);
controllerDeclaration= null;
} }
} }
@ -89,8 +91,8 @@ public class CPPASTSwitchStatement extends ASTNode implements
default : break; default : break;
} }
} }
if( controller != null ) if( !controller.accept( action ) ) return false; if( controllerExpression != null ) if( !controllerExpression.accept( action ) ) return false;
if( decl != null ) if( !decl.accept( action ) ) return false; if( controllerDeclaration != null ) if( !controllerDeclaration.accept( action ) ) return false;
if( body != null ) if( !body.accept( action ) ) return false; if( body != null ) if( !body.accept( action ) ) return false;
if( action.shouldVisitStatements ){ if( action.shouldVisitStatements ){
@ -104,37 +106,30 @@ public class CPPASTSwitchStatement extends ASTNode implements
} }
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
if( body == child ) if (body == child) {
{
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
body = (IASTStatement) other; body = (IASTStatement) other;
} else if (controllerDeclaration == child || controllerExpression == child) {
if (other instanceof IASTExpression) {
setControllerExpression((IASTExpression) other);
} else if (other instanceof IASTDeclaration) {
setControllerDeclaration((IASTDeclaration) 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;
}
} }
public IASTDeclaration getControllerDeclaration() { public IASTDeclaration getControllerDeclaration() {
return decl; return controllerDeclaration;
} }
public void setControllerDeclaration(IASTDeclaration d) { public void setControllerDeclaration(IASTDeclaration d) {
assertNotFrozen(); assertNotFrozen();
decl = d; controllerDeclaration = d;
if (d != null) { if (d != null) {
d.setParent(this); d.setParent(this);
d.setPropertyInParent(CONTROLLER_DECLARATION); 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * 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; 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; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/** /**
* @author jcamelon * While statement in c++.
*/ */
public class CPPASTWhileStatement extends ASTNode implements public class CPPASTWhileStatement extends ASTNode implements
ICPPASTWhileStatement, IASTAmbiguityParent { ICPPASTWhileStatement, IASTAmbiguityParent {
@ -63,6 +64,7 @@ public class CPPASTWhileStatement extends ASTNode implements
if (condition != null) { if (condition != null) {
condition.setParent(this); condition.setParent(this);
condition.setPropertyInParent(CONDITIONEXPRESSION); condition.setPropertyInParent(CONDITIONEXPRESSION);
condition2= null;
} }
} }
@ -89,6 +91,7 @@ public class CPPASTWhileStatement extends ASTNode implements
if (declaration != null) { if (declaration != null) {
declaration.setParent(this); declaration.setParent(this);
declaration.setPropertyInParent(CONDITIONDECLARATION); declaration.setPropertyInParent(CONDITIONDECLARATION);
condition= null;
} }
} }
@ -116,23 +119,17 @@ public class CPPASTWhileStatement extends ASTNode implements
} }
public void replace(IASTNode child, IASTNode other) { public void replace(IASTNode child, IASTNode other) {
if( body == child ) if (body == child) {
{
other.setPropertyInParent(child.getPropertyInParent()); other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent()); other.setParent(child.getParent());
body = (IASTStatement) other; body = (IASTStatement) other;
} }
if( child == condition ) if (child == condition || child == condition2) {
{ if (other instanceof IASTExpression) {
other.setPropertyInParent( child.getPropertyInParent() ); setCondition((IASTExpression) other);
other.setParent( child.getParent() ); } else if (other instanceof IASTDeclaration) {
condition = (IASTExpression) other; setConditionDeclaration((IASTDeclaration) other);
} }
if( condition2 == child )
{
other.setParent( child.getParent() );
other.setPropertyInParent( child.getPropertyInParent() );
condition2 = (IASTDeclaration) other;
} }
} }

View file

@ -3669,26 +3669,57 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
protected IASTNode cppStyleCondition(int expectToken) throws BacktrackException, EndOfFileException { protected IASTNode cppStyleCondition(int expectToken) throws BacktrackException, EndOfFileException {
IASTExpression e= null;
IASTSimpleDeclaration decl= null;
IToken end= null;
IToken mark = mark(); IToken mark = mark();
try { try {
IASTExpression e = expression(); decl= simpleSingleDeclaration(DeclarationOptions.CONDITION);
final int lt1= LT(1); end= LA(1);
if (lt1 == expectToken || lt1 == IToken.tEOC) { final int la= end.getType();
return e; if (la != expectToken && la != IToken.tEOC) {
end= null;
decl= null;
} }
} catch (BacktrackException bt) { } catch (BacktrackException b) {
} }
backup(mark); backup(mark);
try { try {
return simpleSingleDeclaration(DeclarationOptions.CONDITION); e= expression();
} catch (BacktrackException b) {
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) { if (expectToken == IToken.tRPAREN) {
backup(mark); backup(mark);
return skipProblemConditionInParenthesis(mark.getOffset()); return skipProblemConditionInParenthesis(mark.getOffset());
} }
throw b; throw bt;
} }
} }
backup(end);
return decl;
}
@Override @Override

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$
}