1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Cast ambiguities, bug 237057.

This commit is contained in:
Markus Schorn 2008-07-07 13:22:30 +00:00
parent 803729074d
commit 076d4c7899
13 changed files with 984 additions and 293 deletions

View file

@ -19,6 +19,7 @@ import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
@ -28,6 +29,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@ -45,6 +47,7 @@ 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.IASTPreprocessorMacroDefinition;
@ -5039,4 +5042,191 @@ public class AST2Tests extends AST2BaseTest {
assertEquals("foux= 1;", stmt.getRawSignature());
}
}
// typedef int t;
// int a,b;
// void test() {
// b* (t)+a *b // b,t,a,unary+,cast,*,b,*
// b*(a) + a*b // b,a,*,a,b,*,+
// b* (t)-a *b // b,t,a,unary-,cast,*,b,*
// b*(a) - a*b // b,a,*,a,b,*,-
// b* (t)*a *b // b,t,a,unary*,cast,*,b,*
// b*(a) * a * b // b,a,*,a,*,b,*
// b == (t)&a < b // b,t,a,unary&,cast,b,<,==
// b < (t)&a == b // b,t,a,unary&,cast,<,b,==
// b==(a) & a<b // b,a,==,a,b,<,&
// +(t)+1 // t,1,unary+,cast,unary+
// +(a)+1 // a,unary+,1,+
// sizeof +(t)+1 // t,1,unary+,cast,unary+,sizeof
// sizeof +(a)+1 // a,unary+,sizeof,1,+
// b* (t)(t)+a * b // b,t,t,a,unary+,cast,cast,*,b,*
// b* (t)(a)+a * b // b,t,a,cast,*,a,b,*,+
// (int)(t)+1 // int,t,1,unary+,cast,cast
// (int)(a)+1 // int,a,cast,1,+
// a*a*(t)+a*a*a // a,a,*,t,a,unary+,cast,*,a,*,a,*
// (typeof a)(t)-a // typeof a,t,a,unary-,cast,cast
// (typeof a)(a)-a // typeof a,a,cast,a,-
public void testBinaryVsCastAmbiguities_Bug237057() throws Exception {
StringBuffer[] input= getContents(2);
String code= input[0].toString();
String[] samples= input[1].toString().split("\n");
for (ParserLanguage lang : ParserLanguage.values()) {
for (String s : samples) {
final String[] io= s.split("//");
final String exprStr = io[0].trim();
final IASTTranslationUnit tu= parse(code + exprStr + ";}", lang);
final IASTFunctionDefinition fdef= getDeclaration(tu, 2);
IASTExpression expr= getExpressionOfStatement(fdef, 0);
assertEquals("expr: " + exprStr, io[1].trim(), polnishNotation(expr));
assertEquals(exprStr, expr.getRawSignature());
checkOffsets(exprStr, expr);
}
}
}
// struct s {int b;};
// typedef int t;
// struct s* a;
// struct s* f(struct s*);
// void test() {
// (t)(a) // t,a,cast
// (f)(a) // f,a,()
// (t)(t)(a) // t,t,a,cast,cast
// (t)(f)(a) // t,f,a,(),cast
// (f)(a)(a) // f,a,(),a,()
// (t)(f)(a)++ // t,f,a,(),++,cast
// (t)(t)(a)++ // t,t,a,++,cast,cast
// (t)(f)(a)-- // t,f,a,(),--,cast
// (t)(t)(a)-- // t,t,a,--,cast,cast
// (t)(f)(a)[0] // t,f,a,(),0,[],cast
// (t)(t)(a)[0] // t,t,a,0,[],cast,cast
// (t)(f)(a)->b // t,f,a,(),b,->,cast
// (t)(t)(a)->b // t,t,a,b,->,cast,cast
// (t)(a)+1 // t,a,cast,1,+
// (f)(a)+1 // f,a,(),1,+
// (t)(t)+1 // t,t,1,unary+,cast,cast
public void testCastVsFunctionCallAmbiguities_Bug237057() throws Exception {
StringBuffer[] input= getContents(2);
String code= input[0].toString();
String[] samples= input[1].toString().split("\n");
for (ParserLanguage lang : ParserLanguage.values()) {
for (String s : samples) {
final String[] io= s.split("//");
final String exprStr = io[0].trim();
final IASTTranslationUnit tu= parse(code + exprStr + ";}", lang);
final IASTFunctionDefinition fdef= getDeclaration(tu, 4);
IASTExpression expr= getExpressionOfStatement(fdef, 0);
assertEquals("expr: " + exprStr, io[1].trim(), polnishNotation(expr));
assertEquals(exprStr, expr.getRawSignature());
checkOffsets(exprStr, expr);
}
}
}
private void checkOffsets(String exprStr, IASTExpression expr) {
if (expr instanceof IASTBinaryExpression) {
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
checkOffsets(exprStr, bexpr.getOperand1());
checkOffsets(exprStr, bexpr.getOperand2());
assertEquals("in expr: " + exprStr, offset(bexpr), offset(bexpr.getOperand1()));
assertTrue("in expr: " + exprStr, endOffset(bexpr.getOperand1()) < offset(bexpr.getOperand2()));
assertEquals("in expr: " + exprStr, endOffset(bexpr), endOffset(bexpr.getOperand2()));
} else if (expr instanceof IASTCastExpression) {
IASTCastExpression castExpr= (IASTCastExpression) expr;
checkOffsets(exprStr, castExpr.getOperand());
assertTrue("in expr: " + exprStr, offset(castExpr) < offset(castExpr.getTypeId()));
assertTrue("in expr: " + exprStr, endOffset(castExpr.getTypeId()) < offset(castExpr.getOperand()));
assertEquals("in expr: " + exprStr, endOffset(castExpr), endOffset(castExpr.getOperand()));
} else if (expr instanceof IASTUnaryExpression) {
IASTUnaryExpression unaryExpr= (IASTUnaryExpression) expr;
checkOffsets(exprStr, unaryExpr.getOperand());
switch (unaryExpr.getOperator()) {
case IASTUnaryExpression.op_bracketedPrimary:
assertTrue("in expr: " + exprStr, offset(unaryExpr) < offset(unaryExpr.getOperand()));
assertTrue("in expr: " + exprStr, endOffset(unaryExpr.getOperand()) < endOffset(unaryExpr));
break;
case IASTUnaryExpression.op_postFixDecr:
case IASTUnaryExpression.op_postFixIncr:
assertEquals("in expr: " + exprStr, offset(expr), offset(unaryExpr.getOperand()));
assertTrue("in expr: " + exprStr, endOffset(unaryExpr.getOperand()) < endOffset(expr));
break;
default:
assertTrue("in expr: " + exprStr, offset(unaryExpr) < offset(unaryExpr.getOperand()));
assertEquals("in expr: " + exprStr, endOffset(unaryExpr), endOffset(unaryExpr.getOperand()));
break;
}
}
}
private int offset(IASTNode expr) {
return ((ASTNode) expr).getOffset();
}
private int endOffset(IASTNode expr) {
return ((ASTNode) expr).getOffset() + ((ASTNode) expr).getLength();
}
private String polnishNotation(IASTExpression expr) {
StringBuilder buf= new StringBuilder();
polnishNotation(expr, buf);
return buf.toString();
}
private void polnishNotation(IASTExpression expr, StringBuilder buf) {
if (expr instanceof IASTBinaryExpression) {
IASTBinaryExpression bexpr= (IASTBinaryExpression) expr;
polnishNotation(bexpr.getOperand1(), buf);
buf.append(',');
polnishNotation(bexpr.getOperand2(), buf);
buf.append(',');
buf.append(ASTSignatureUtil.getBinaryOperatorString(bexpr));
} else if (expr instanceof IASTCastExpression) {
IASTCastExpression castExpr= (IASTCastExpression) expr;
buf.append(castExpr.getTypeId().getRawSignature());
buf.append(',');
polnishNotation(castExpr.getOperand(), buf);
buf.append(",cast");
} else if (expr instanceof IASTFunctionCallExpression) {
IASTFunctionCallExpression f= (IASTFunctionCallExpression) expr;
polnishNotation(f.getFunctionNameExpression(), buf);
buf.append(',');
polnishNotation(f.getParameterExpression(), buf);
buf.append(",()");
} else if (expr instanceof IASTArraySubscriptExpression) {
IASTArraySubscriptExpression f= (IASTArraySubscriptExpression) expr;
polnishNotation(f.getArrayExpression(), buf);
buf.append(',');
polnishNotation(f.getSubscriptExpression(), buf);
buf.append(",[]");
} else if (expr instanceof IASTFieldReference) {
IASTFieldReference f= (IASTFieldReference) expr;
polnishNotation(f.getFieldOwner(), buf);
buf.append(',');
buf.append(f.getFieldName().toString());
buf.append(',');
buf.append(f.isPointerDereference() ? "->" : ".");
} else if (expr instanceof IASTUnaryExpression) {
IASTUnaryExpression unaryExpr= (IASTUnaryExpression) expr;
polnishNotation(unaryExpr.getOperand(), buf);
switch (unaryExpr.getOperator()) {
case IASTUnaryExpression.op_amper:
case IASTUnaryExpression.op_plus:
case IASTUnaryExpression.op_minus:
case IASTUnaryExpression.op_star:
buf.append(",unary");
buf.append(ASTSignatureUtil.getUnaryOperatorString(unaryExpr));
break;
case IASTUnaryExpression.op_bracketedPrimary:
break;
default:
buf.append(',');
buf.append(ASTSignatureUtil.getUnaryOperatorString(unaryExpr));
break;
}
} else {
buf.append(expr.getRawSignature());
}
}
}

View file

@ -20,7 +20,6 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
import org.eclipse.cdt.core.dom.ast.c.ICASTPointer;
import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
@ -37,7 +36,6 @@ import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier;
@ -925,29 +923,6 @@ public class ASTSignatureUtil {
public static String getBinaryOperatorString(IASTBinaryExpression be) {
int op = be.getOperator();
String opString = EMPTY_STRING;
if (be instanceof ICPPASTBinaryExpression) {
switch(op) {
case ICPPASTBinaryExpression.op_pmarrow:
opString = String.valueOf(Keywords.cpARROW);
break;
case ICPPASTBinaryExpression.op_pmdot:
opString = String.valueOf(Keywords.cpDOT);
break;
}
} else if (be instanceof IGPPASTBinaryExpression) {
switch(op) {
case IGPPASTBinaryExpression.op_max:
opString = String.valueOf(Keywords.cpMAX);
break;
case IGPPASTBinaryExpression.op_min:
opString = String.valueOf(Keywords.cpMIN);
break;
}
}
if (!opString.equals(EMPTY_STRING)) return opString;
switch(op) {
case IASTBinaryExpression.op_multiply:
opString = String.valueOf(Keywords.cpSTAR);
@ -1036,12 +1011,18 @@ public class ASTSignatureUtil {
case IASTBinaryExpression.op_notequals:
opString = String.valueOf(Keywords.cpNOTEQUAL);
break;
case IGPPASTBinaryExpression.op_max:
case IASTBinaryExpression.op_max:
opString = String.valueOf(Keywords.cpMAX);
break;
case IGPPASTBinaryExpression.op_min:
case IASTBinaryExpression.op_min:
opString = String.valueOf(Keywords.cpMIN);
break;
case IASTBinaryExpression.op_pmarrow:
opString = String.valueOf(Keywords.cpARROW);
break;
case IASTBinaryExpression.op_pmdot:
opString = String.valueOf(Keywords.cpDOT);
break;
}
return opString;

View file

@ -0,0 +1,258 @@
/*******************************************************************************
* Copyright (c) 2008 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;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode.NameCollector;
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
import org.eclipse.core.runtime.Assert;
/**
* Handles the ambiguity between a binary- and a cast-expression. (type)+var versus (var)+var.
* It also handles the impact on the grouping of the sub-expressions.
*/
public abstract class ASTAmbiguousBinaryVsCastExpression extends ASTNode implements IASTAmbiguousExpression {
private final IASTBinaryExpression fBinaryExpression;
private final IASTCastExpression fCastExpression;
/**
* The binary expression must have one of the following operators: +,-,&,*. The left hand side of the binary expression
* must end with an expression in parenthesis (which could be read as the beginning of the cast-expression.
* The cast-expression must contain the type-id (corresponding to the last expression in parenthesis on the left side of the
* binary expression. The operand of the castExpression can be <code>null</code>, it will be computed from the binary expression.
*/
public ASTAmbiguousBinaryVsCastExpression(IASTBinaryExpression binaryExpression, IASTCastExpression castExpression) {
fBinaryExpression= binaryExpression;
fCastExpression= castExpression;
}
public void addExpression(IASTExpression e) {
Assert.isLegal(false);
}
public IType getExpressionType() {
return CVisitor.getExpressionType(getExpressions()[0]);
}
public IASTExpression[] getExpressions() {
return new IASTExpression[] {fBinaryExpression, fCastExpression};
}
@Override
public boolean accept(ASTVisitor visitor) {
final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
IASTNode nodeToReplace= this;
// handle nested ambiguities first
owner.replace(nodeToReplace, fCastExpression);
nodeToReplace= fCastExpression;
fCastExpression.getTypeId().accept(visitor);
owner.replace(nodeToReplace, fBinaryExpression);
nodeToReplace= fBinaryExpression;
fBinaryExpression.accept(visitor);
// find nested names
final NameCollector nameCollector= new NameCollector();
fCastExpression.getTypeId().accept(nameCollector);
final IASTName[] names= nameCollector.getNames();
// resolve names
boolean hasIssue= false;
for (IASTName name : names) {
try {
IBinding b = name.resolveBinding();
if (b instanceof IProblemBinding) {
hasIssue= true;
break;
}
} catch (Exception t) {
hasIssue= true;
break;
}
}
if (hasIssue) {
return true;
}
final IASTExpression left = fBinaryExpression.getOperand1();
final IASTExpression right = fBinaryExpression.getOperand2();
left.setParent(null);
right.setParent(null);
IASTUnaryExpression primaryInParenthesis= findTrailingBracketedPrimaryExpression(left);
IASTExpression leadingCastExpression= findLeadingCastExpression(right);
IASTExpression castedUnary= fCastExpression.getOperand();
if (primaryInParenthesis != null && leadingCastExpression != null && castedUnary instanceof IASTUnaryExpression) {
IASTExpression lp= (IASTExpression) primaryInParenthesis.getParent();
IASTBinaryExpression rp= (IASTBinaryExpression) leadingCastExpression.getParent();
((IASTUnaryExpression)castedUnary).setOperand(leadingCastExpression);
setEnd(castedUnary, leadingCastExpression);
setRange(fCastExpression, primaryInParenthesis, leadingCastExpression);
IASTExpression root= joinExpressions(lp, fCastExpression, rp);
if (root != null) {
owner.replace(nodeToReplace, root);
return true;
}
}
return true;
}
private void setEnd(IASTNode node, IASTNode end) {
final ASTNode target= (ASTNode) node;
final ASTNode e= (ASTNode) end;
target.setLength(e.getOffset() + e.getLength() - target.getOffset());
}
private void setStart(IASTNode node, IASTNode start) {
final ASTNode target= (ASTNode) node;
final int offset = ((ASTNode) start).getOffset();
target.setOffsetAndLength(offset, target.getOffset() + target.getLength() - offset);
}
private void setRange(IASTNode node, IASTNode from, IASTNode to) {
final int offset = ((ASTNode) from).getOffset();
final ASTNode t= (ASTNode) to;
((ASTNode) node).setOffsetAndLength(offset, t.getOffset()+t.getLength()-offset);
}
/**
* @param l unary, cast or binary expression to the left, all parents are unary, cast or binary expressions.
* @param middle initially a cast-expression, always suitable to put into l or r
* @param r a binary expression to the right, all parents are binary expressions.
*/
private IASTExpression joinExpressions(IASTExpression l, IASTExpression middle, IASTBinaryExpression r) {
while (true) {
if (l == null) {
if (r == null) {
return middle;
}
r.setOperand1(middle);
setStart(r, middle);
middle= r;
r= (IASTBinaryExpression) r.getParent();
} else if (l instanceof IASTCastExpression) {
// cast binds stronger than binary operator
((IASTCastExpression) l).setOperand(middle);
setEnd(l, middle);
middle= l; // middle becomes cast-expr, can be put into r (a binary-expr)
l= (IASTExpression) l.getParent();
} else if (l instanceof IASTUnaryExpression) { //
// unary operator binds stronger than binary operator
((IASTUnaryExpression) l).setOperand(middle);
setEnd(l, middle);
middle= l; // middle becomes unary-expr, can be put into r (a binary-expr)
l= (IASTExpression) l.getParent();
} else {
if (r== null || getPrecendence((IASTBinaryExpression) l) >= getPrecendence(r)) {
((IASTBinaryExpression)l).setOperand2(middle);
setEnd(l, middle);
middle= l; // middle becomes binary, can be put into r because precedence is greater or equal.
l= (IASTExpression) l.getParent();
} else {
r.setOperand1(middle);
setStart(r, middle);
middle= r; // middle becomes binary, can be put into r because precedence is greater.
r= (IASTBinaryExpression) r.getParent();
}
}
}
}
private int getPrecendence(IASTBinaryExpression r) {
switch(r.getOperator()) {
case IASTBinaryExpression.op_ellipses:
case IASTBinaryExpression.op_assign:
case IASTBinaryExpression.op_binaryAndAssign:
case IASTBinaryExpression.op_binaryOrAssign:
case IASTBinaryExpression.op_binaryXorAssign:
case IASTBinaryExpression.op_divideAssign:
case IASTBinaryExpression.op_minusAssign:
case IASTBinaryExpression.op_moduloAssign:
case IASTBinaryExpression.op_multiplyAssign:
case IASTBinaryExpression.op_plusAssign:
case IASTBinaryExpression.op_shiftLeftAssign:
case IASTBinaryExpression.op_shiftRightAssign:
return 0;
case IASTBinaryExpression.op_logicalOr:
return 1;
case IASTBinaryExpression.op_logicalAnd:
return 2;
case IASTBinaryExpression.op_binaryOr:
return 3;
case IASTBinaryExpression.op_binaryXor:
return 4;
case IASTBinaryExpression.op_binaryAnd:
return 5;
case IASTBinaryExpression.op_equals:
case IASTBinaryExpression.op_notequals:
return 6;
case IASTBinaryExpression.op_greaterThan:
case IASTBinaryExpression.op_greaterEqual:
case IASTBinaryExpression.op_lessThan:
case IASTBinaryExpression.op_lessEqual:
case IASTBinaryExpression.op_max:
case IASTBinaryExpression.op_min:
return 7;
case IASTBinaryExpression.op_shiftLeft:
case IASTBinaryExpression.op_shiftRight:
return 8;
case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_minus:
return 9;
case IASTBinaryExpression.op_multiply:
case IASTBinaryExpression.op_divide:
case IASTBinaryExpression.op_modulo:
return 10;
case IASTBinaryExpression.op_pmarrow:
case IASTBinaryExpression.op_pmdot:
return 11;
}
assert false;
return 0;
}
private IASTUnaryExpression findTrailingBracketedPrimaryExpression(IASTExpression expr) {
while(true) {
if (expr instanceof IASTBinaryExpression) {
expr= ((IASTBinaryExpression) expr).getOperand2();
} else if (expr instanceof IASTCastExpression) {
expr= ((IASTCastExpression)expr).getOperand();
} else if (expr instanceof IASTUnaryExpression) {
IASTUnaryExpression u= (IASTUnaryExpression) expr;
if (u.getOperator() == IASTUnaryExpression.op_bracketedPrimary)
return u;
expr= u.getOperand();
} else {
return null;
}
}
}
private IASTExpression findLeadingCastExpression(IASTExpression expr) {
while (expr instanceof IASTBinaryExpression) {
expr= ((IASTBinaryExpression) expr).getOperand1();
}
return expr;
}
}

View file

@ -0,0 +1,185 @@
/*******************************************************************************
* Copyright (c) 2008 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;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode.NameCollector;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.Assert;
/**
* Handles the ambiguity between cast and function-call expressions: (type)(expr) versus (function)(expr);
* It also handles the impact on the grouping of the sub-expressions.
*/
public abstract class ASTAmbiguousCastVsFunctionCallExpression extends ASTNode implements IASTAmbiguousExpression {
private final IASTCastExpression fCastExpression;
private final IASTFunctionCallExpression fFunctionCallExpression;
/**
* The operand of the cast expression must start with an expression in parenthesis (which could be read as the parameter
* list of the function call).
* The function-call must contain the name expression (corresponding to the type-id of the cast expression). The parameter
* expression may be <code>null</code>, it will be computed from the cast expression.
*/
public ASTAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpression, IASTFunctionCallExpression functionCall) {
fCastExpression= castExpression;
fFunctionCallExpression= functionCall;
}
public void addExpression(IASTExpression e) {
Assert.isLegal(false);
}
public IType getExpressionType() {
return CPPVisitor.getExpressionType(getExpressions()[0]);
}
public IASTExpression[] getExpressions() {
return new IASTExpression[] {fCastExpression, fFunctionCallExpression};
}
@Override
public boolean accept(ASTVisitor visitor) {
final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
IASTNode nodeToReplace= this;
// try cast-expression
owner.replace(nodeToReplace, fCastExpression);
nodeToReplace= fCastExpression;
// resolve nested ambiguities
fCastExpression.accept(visitor);
// if the operand of the cast-expr is not suitable for a function call, we are done.
final IASTUnaryExpression primaryWithParenthesis= findPrimaryExpressionInParenthesis(fCastExpression.getOperand());
if (primaryWithParenthesis == null)
return true;
// find nested names
final NameCollector nameCollector= new NameCollector();
fCastExpression.getTypeId().accept(nameCollector);
final IASTName[] names= nameCollector.getNames();
// resolve names
boolean hasIssue= false;
for (IASTName name : names) {
try {
IBinding b = name.resolveBinding();
if (b instanceof IProblemBinding) {
hasIssue= true;
break;
}
} catch (Exception t) {
hasIssue= true;
break;
}
}
if (!hasIssue)
return true;
fFunctionCallExpression.setParameterExpression(primaryWithParenthesis.getOperand());
setRange(fFunctionCallExpression, fCastExpression, primaryWithParenthesis);
IASTExpression result= fFunctionCallExpression;
IASTExpression postFix= fCastExpression.getOperand();
if (postFix != primaryWithParenthesis) {
result= postFix;
while (true) {
setStart(postFix, fFunctionCallExpression);
if (postFix instanceof IASTArraySubscriptExpression) {
final IASTArraySubscriptExpression ase = (IASTArraySubscriptExpression) postFix;
postFix= ase.getArrayExpression();
if (postFix == primaryWithParenthesis) {
ase.setArrayExpression(fFunctionCallExpression);
break;
}
} else if (postFix instanceof IASTFunctionCallExpression) {
final IASTFunctionCallExpression fc = (IASTFunctionCallExpression) postFix;
postFix= fc.getFunctionNameExpression();
if (postFix == primaryWithParenthesis) {
fc.setFunctionNameExpression(fFunctionCallExpression);
break;
}
} else if (postFix instanceof IASTFieldReference) {
final IASTFieldReference fr = (IASTFieldReference) postFix;
postFix= fr.getFieldOwner();
if (postFix == primaryWithParenthesis) {
fr.setFieldOwner(fFunctionCallExpression);
break;
}
} else {
final IASTUnaryExpression ue = (IASTUnaryExpression) postFix;
postFix= ue.getOperand();
if (postFix == primaryWithParenthesis) {
ue.setOperand(fFunctionCallExpression);
break;
}
}
}
}
owner.replace(nodeToReplace, result);
// resolve ambiguities in the function-call expression
fFunctionCallExpression.getFunctionNameExpression().accept(visitor);
return true;
}
private IASTUnaryExpression findPrimaryExpressionInParenthesis(IASTExpression operand) {
while (true) {
if (operand instanceof IASTUnaryExpression) {
final IASTUnaryExpression unary= (IASTUnaryExpression) operand;
switch (unary.getOperator()) {
case IASTUnaryExpression.op_bracketedPrimary:
return unary;
case IASTUnaryExpression.op_postFixDecr:
case IASTUnaryExpression.op_postFixIncr:
operand= unary.getOperand();
break;
default:
return null;
}
}
else if (operand instanceof IASTArraySubscriptExpression) {
operand= ((IASTArraySubscriptExpression) operand).getArrayExpression();
} else if (operand instanceof IASTFunctionCallExpression) {
operand= ((IASTFunctionCallExpression) operand).getFunctionNameExpression();
} else if (operand instanceof IASTFieldReference) {
operand= ((IASTFieldReference) operand).getFieldOwner();
} else {
return null;
}
}
}
private void setStart(IASTNode node, IASTNode start) {
final ASTNode target= (ASTNode) node;
final int offset = ((ASTNode) start).getOffset();
target.setOffsetAndLength(offset, target.getOffset() + target.getLength() - offset);
}
private void setRange(IASTNode node, IASTNode from, IASTNode to) {
final int offset = ((ASTNode) from).getOffset();
final ASTNode t= (ASTNode) to;
((ASTNode) node).setOffsetAndLength(offset, t.getOffset()+t.getLength()-offset);
}
}

View file

@ -63,9 +63,6 @@ import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider;
import org.eclipse.cdt.core.dom.parser.ISourceCodeParser;
import org.eclipse.cdt.core.parser.AbstractParserLogService;
@ -111,12 +108,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IToken currToken;
protected int eofOffset;
protected boolean onTopInTemplateArgs= false;
protected boolean inBinaryExpression= true;
protected boolean isCancelled = false;
protected boolean parsePassed = true;
protected int backtrackCount = 0;
protected BacktrackException backtrack = new BacktrackException();
protected ASTCompletionNode completionNode;
protected IASTTypeId fTypeIdForCastAmbiguity;
protected AbstractGNUSourceCodeParser(IScanner scanner,
IParserLogService logService, ParserMode parserMode,
@ -325,8 +325,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
throw exception;
}
protected static final char[] EMPTY_STRING = "".toCharArray(); //$NON-NLS-1$
/**
* Mark our place in the buffer so that we could return to it should we have
* to.
@ -769,10 +767,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
operator = IASTBinaryExpression.op_greaterEqual;
break;
case IGCCToken.tMAX:
operator = IGPPASTBinaryExpression.op_max;
operator = IASTBinaryExpression.op_max;
break;
case IGCCToken.tMIN:
operator = IGPPASTBinaryExpression.op_min;
operator = IASTBinaryExpression.op_min;
break;
default:
return result;
@ -783,36 +781,68 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
}
}
protected abstract IASTExpression multiplicativeExpression()
throws BacktrackException, EndOfFileException;
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLPAREN) {
final IToken mark = mark();
final int startingOffset = mark.getOffset();
consume();
if (!avoidCastExpressionByHeuristics()) {
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
try {
IASTExpression castExpression = castExpression();
return buildTypeIdUnaryExpression(IASTCastExpression.op_cast,
typeId, castExpression, startingOffset,
LT(1) == IToken.tEOC ? LA(1).getEndOffset() : calculateEndOffset(castExpression));
} catch (BacktrackException b) {
}
}
}
backup(mark);
}
return unaryExpression();
if (LT(1) == IToken.tLPAREN) {
final IToken mark= mark();
final int startingOffset= mark.getOffset();
consume();
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
boolean unaryFailed= false;
if (inBinaryExpression) {
switch (LT(1)){
// ambiguity with unary operator
case IToken.tPLUS: case IToken.tMINUS:
case IToken.tSTAR: case IToken.tAMPER:
IToken markEnd= mark();
backup(mark);
try {
IASTExpression unary= unaryExpression();
fTypeIdForCastAmbiguity= typeId;
return unary;
} catch (BacktrackException bt) {
backup(markEnd);
unaryFailed= true;
}
}
}
try {
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
IASTExpression rhs= castExpression();
IASTCastExpression result= buildCastExpression(IASTCastExpression.op_cast, typeId, rhs, startingOffset, calculateEndOffset(rhs));
if (!unaryFailed && couldBeFunctionCall && rhs instanceof IASTCastExpression == false) {
IToken markEnd= mark();
final IASTTypeId typeidForCastAmbiguity= fTypeIdForCastAmbiguity;
backup(mark);
try {
IASTExpression expr= primaryExpression();
IASTFunctionCallExpression fcall= createFunctionCallExpression();
fcall.setFunctionNameExpression(expr);
IASTAmbiguousExpression ambiguity= createAmbiguousCastVsFunctionCallExpression(result, fcall);
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
return ambiguity;
} catch (BacktrackException bt) {
} finally {
backup(markEnd);
fTypeIdForCastAmbiguity= typeidForCastAmbiguity;
}
}
return result;
} catch (BacktrackException b) {
if (unaryFailed)
throw b;
}
}
backup(mark);
}
return unaryExpression();
}
protected abstract IASTExpression unaryExpression() throws BacktrackException, EndOfFileException;
protected abstract IASTExpression primaryExpression() throws BacktrackException, EndOfFileException;
protected abstract IASTExpression buildTypeIdExpression(int op,
IASTTypeId typeId, int startingOffset, int endingOffset);
@ -939,11 +969,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IASTExpression andExpression() throws EndOfFileException, BacktrackException {
IASTExpression firstExpression = equalityExpression();
while (LT(1) == IToken.tAMPER) {
consume();
final int offset= consume().getOffset();
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
IASTExpression secondExpression = equalityExpression();
firstExpression = buildBinaryExpression(
IASTBinaryExpression.op_binaryAnd, firstExpression,
secondExpression, calculateEndOffset(secondExpression));
if (typeid != null) {
firstExpression = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) firstExpression, typeid, IASTUnaryExpression.op_amper, offset);
}
}
return firstExpression;
}
@ -982,6 +1016,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
}
protected abstract IASTBinaryExpression createBinaryExpression();
protected abstract IASTFunctionCallExpression createFunctionCallExpression();
protected IASTExpression shiftExpression() throws BacktrackException,
EndOfFileException {
@ -1004,26 +1039,75 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
}
}
protected IASTExpression additiveExpression() throws BacktrackException,
EndOfFileException {
IASTExpression firstExpression = multiplicativeExpression();
protected IASTExpression additiveExpression() throws BacktrackException, EndOfFileException {
IASTExpression result= multiplicativeExpression();
for (;;) {
int operator;
int unaryOperator;
switch (LT(1)) {
case IToken.tPLUS:
operator= IASTBinaryExpression.op_plus;
unaryOperator= IASTUnaryExpression.op_plus;
break;
case IToken.tMINUS:
IToken t = consume();
int operator = (t.getType() == IToken.tPLUS) ? IASTBinaryExpression.op_plus
: IASTBinaryExpression.op_minus;
IASTExpression secondExpression = multiplicativeExpression();
firstExpression = buildBinaryExpression(operator,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
operator= IASTBinaryExpression.op_minus;
unaryOperator= IASTUnaryExpression.op_minus;
break;
default:
return firstExpression;
return result;
}
final int offset= consume().getOffset();
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
IASTExpression secondExpression = multiplicativeExpression();
result = buildBinaryExpression(operator, result, secondExpression,
calculateEndOffset(secondExpression));
if (typeid != null) {
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result, typeid, unaryOperator, offset);
}
}
}
protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException {
inBinaryExpression= true;
fTypeIdForCastAmbiguity= null;
IASTExpression result= pmExpression();
for (;;) {
int operator;
switch (LT(1)) {
case IToken.tSTAR:
operator = IASTBinaryExpression.op_multiply;
break;
case IToken.tDIV:
operator = IASTBinaryExpression.op_divide;
break;
case IToken.tMOD:
operator = IASTBinaryExpression.op_modulo;
break;
default:
return result;
}
final int offset= consume().getOffset();
final IASTTypeId typeid= fTypeIdForCastAmbiguity; fTypeIdForCastAmbiguity= null;
IASTExpression secondExpression= pmExpression();
result= buildBinaryExpression(operator, result, secondExpression, calculateEndOffset(secondExpression));
if (typeid != null) {
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result, typeid, IASTUnaryExpression.op_star, offset);
}
}
}
protected abstract IASTExpression pmExpression() throws EndOfFileException, BacktrackException;
private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpression expr, final IASTTypeId typeid, int unaryOperator, int unaryOpOffset) {
IASTUnaryExpression unary= createUnaryExpression();
unary.setOperator(unaryOperator);
((ASTNode) unary).setOffset(unaryOpOffset);
IASTCastExpression castExpr= buildCastExpression(IASTCastExpression.op_cast, typeid, unary, 0, 0);
IASTExpression result= createAmbiguousBinaryVsCastExpression(expr, castExpr);
((ASTNode) result).setOffsetAndLength((ASTNode) expr);
return result;
}
protected IASTExpression conditionalExpression() throws BacktrackException,
EndOfFileException {
@ -1069,77 +1153,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected abstract IASTUnaryExpression createUnaryExpression();
protected IASTExpression unaryAlignofExpression()
throws EndOfFileException, BacktrackException {
int offset = consume().getOffset(); // t___alignof__
IASTTypeId d = null;
IASTExpression unaryExpression = null;
IToken m = mark();
int lastOffset = 0;
if (LT(1) == IToken.tLPAREN) {
boolean needBack = false;
try {
consume();
d = typeId(DeclarationOptions.TYPEID);
if (d == null)
needBack = true;
else
lastOffset = consume(IToken.tRPAREN).getEndOffset();
} catch (BacktrackException bt) {
needBack = true;
}
if (needBack) {
backup(m);
d = null;
unaryExpression = unaryExpression();
lastOffset = calculateEndOffset(unaryExpression);
}
} else {
unaryExpression = unaryExpression();
lastOffset = calculateEndOffset(unaryExpression);
}
if (d != null & unaryExpression == null)
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_alignof, d,
offset, lastOffset);
else if (unaryExpression != null && d == null)
return buildUnaryExpression(IGNUASTUnaryExpression.op_alignOf,
unaryExpression, offset, lastOffset);
return null;
}
protected IASTExpression unaryTypeofExpression() throws EndOfFileException,
BacktrackException {
int offset = consume().getOffset(); // t_typeof
IASTTypeId d = null;
IASTExpression expression = null;
int lastOffset = 0;
// prefer expressions over type-ids
if (LT(1) == IToken.tLPAREN && LT(2) != IToken.tLBRACE) {
consume();
final IToken m = mark();
try {
expression= expression();
}
catch (BacktrackException e) {
backup(m);
d = typeId(DeclarationOptions.TYPEID);
if (d == null)
throw e;
}
lastOffset = consume(IToken.tRPAREN).getEndOffset();
} else {
expression = unaryExpression();
lastOffset = calculateEndOffset(expression);
}
if (d != null)
return buildTypeIdExpression(IGNUASTTypeIdExpression.op_typeof, d, offset, lastOffset);
return buildUnaryExpression(IGNUASTUnaryExpression.op_typeof, expression, offset, lastOffset);
}
protected IASTStatement handleFunctionBody() throws BacktrackException, EndOfFileException {
declarationMark= null;
if (mode == ParserMode.QUICK_PARSE || mode == ParserMode.STRUCTURAL_PARSE) {
@ -1556,17 +1569,15 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected abstract IASTASMDeclaration createASMDirective();
protected IASTExpression buildTypeIdUnaryExpression(int op,
IASTTypeId typeId, IASTExpression subExpression,
int startingOffset, int lastOffset) {
protected IASTCastExpression buildCastExpression(int op, IASTTypeId typeId, IASTExpression operand,
int offset, int endOffset) {
IASTCastExpression result = createCastExpression();
result.setOperator(op);
((ASTNode) result).setOffsetAndLength(startingOffset, lastOffset - startingOffset);
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
result.setTypeId(typeId);
if (subExpression != null) { // which it can be in a completion
result.setOperand(subExpression);
if (operand != null) { // which it can be in a completion
result.setOperand(operand);
}
return result;
}
@ -1989,7 +2000,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
throwBacktrack(token.getOffset(), token.getLength());
}
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis, int offset, int typeExprKind, int unaryExprKind) throws BacktrackException, EndOfFileException {
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
int offset, int typeExprKind, int unaryExprKind) throws BacktrackException, EndOfFileException {
IASTTypeId typeid;
IASTExpression expr= null;
IToken typeidLA= null;
@ -2044,11 +2056,10 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
try {
if (exprIsLimitedToParenthesis) {
consume(IToken.tLPAREN);
}
expr= unaryExpression();
if (exprIsLimitedToParenthesis) {
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
} else {
expr= expression();
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
} else {
expr= unaryExpression();
endOffset2= calculateEndOffset(expr);
}
} catch (BacktrackException bte) {
@ -2078,19 +2089,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
}
protected abstract IASTAmbiguousExpression createAmbiguousExpression();
protected abstract IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr);
protected abstract IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall);
protected IASTExpression parseSizeofExpression() throws BacktrackException, EndOfFileException {
final int offset = consume().getOffset(); // t_sizeof
if (LT(1) != IToken.tLPAREN) {
IASTExpression unary= unaryExpression();
return buildUnaryExpression(IASTUnaryExpression.op_sizeof, unary, offset, calculateEndOffset(unary));
}
return parseTypeidInParenthesisOrUnaryExpression(false, offset, IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof);
}
/**
* @throws BacktrackException
*/
protected IASTStatement forInitStatement(DeclarationOptions option) throws BacktrackException, EndOfFileException {
if( LT(1) == IToken.tSEMI )
return parseNullStatement();

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2008 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.c;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousBinaryVsCastExpression;
public class CASTAmbiguousBinaryVsCastExpression extends ASTAmbiguousBinaryVsCastExpression {
public CASTAmbiguousBinaryVsCastExpression(IASTBinaryExpression binaryExpr, IASTCastExpression castExpr) {
super(binaryExpr, castExpr);
}
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2008 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.c;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousCastVsFunctionCallExpression;
public class CASTAmbiguousCastVsFunctionCallExpression extends ASTAmbiguousCastVsFunctionCallExpression {
public CASTAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall) {
super(castExpr, funcCall);
}
}

View file

@ -9,21 +9,19 @@
* IBM Corporation - initial API and implementation
* Emanuel Graf IFS - Bugfix for #198257
*******************************************************************************/
/*
* Created on May 18, 2005
*/
package org.eclipse.cdt.internal.core.dom.parser.c;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTSimpleDeclSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author aniefer
*
*/
public class GCCASTSimpleDeclSpecifier extends CASTSimpleDeclSpecifier implements IGCCASTSimpleDeclSpecifier {
public class GCCASTSimpleDeclSpecifier extends CASTSimpleDeclSpecifier implements IGCCASTSimpleDeclSpecifier, IASTAmbiguityParent {
private IASTExpression typeOfExpression;
@ -68,4 +66,12 @@ public class GCCASTSimpleDeclSpecifier extends CASTSimpleDeclSpecifier implement
return true;
}
public void replace(IASTNode child, IASTNode other) {
if (child == typeOfExpression) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
typeOfExpression= (IASTExpression) other;
}
}
}

View file

@ -92,6 +92,8 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression;
import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTSimpleDeclSpecifier;
@ -577,36 +579,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
}
@Override
protected IASTExpression multiplicativeExpression()
throws BacktrackException, EndOfFileException {
IASTExpression firstExpression = castExpression();
for (;;) {
switch (LT(1)) {
case IToken.tSTAR:
case IToken.tDIV:
case IToken.tMOD:
IToken t = consume();
IASTExpression secondExpression = castExpression();
int operator = 0;
switch (t.getType()) {
case IToken.tSTAR:
operator = IASTBinaryExpression.op_multiply;
break;
case IToken.tDIV:
operator = IASTBinaryExpression.op_divide;
break;
case IToken.tMOD:
operator = IASTBinaryExpression.op_modulo;
break;
}
firstExpression = buildBinaryExpression(operator,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
default:
return firstExpression;
}
}
protected IASTExpression pmExpression() throws BacktrackException, EndOfFileException {
return castExpression();
}
@Override
@ -630,19 +604,15 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tDECR:
return unaryOperatorCastExpression(IASTUnaryExpression.op_prefixDecr);
case IToken.t_sizeof:
return parseSizeofExpression();
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof);
case IGCCToken.t_typeof:
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof);
case IGCCToken.t___alignof__:
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf);
default:
if (LT(1) == IGCCToken.t_typeof && supportTypeOfUnaries) {
IASTExpression unary = unaryTypeofExpression();
if (unary != null)
return unary;
}
if (LT(1) == IGCCToken.t___alignof__ && supportAlignOfUnaries) {
IASTExpression align = unaryAlignofExpression();
if (align != null)
return align;
}
return postfixExpression();
}
}
@ -791,7 +761,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
}
}
protected IASTFunctionCallExpression createFunctionCallExpression() {
@Override
protected IASTFunctionCallExpression createFunctionCallExpression() {
return new CASTFunctionCallExpression();
}
@ -816,7 +787,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
return new CASTFieldReference();
}
protected IASTExpression primaryExpression() throws EndOfFileException,
@Override
protected IASTExpression primaryExpression() throws EndOfFileException,
BacktrackException {
IToken t = null;
IASTLiteralExpression literalExpression = null;
@ -1224,7 +1196,14 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
if (encounteredRawType || encounteredTypename)
throwBacktrack(LA(1));
typeofExpression = unaryTypeofExpression();
final boolean wasInBinary= inBinaryExpression;
try {
inBinaryExpression= false;
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
} finally {
inBinaryExpression= wasInBinary;
}
encounteredTypename= true;
endOffset= calculateEndOffset(typeofExpression);
break;
@ -2192,7 +2171,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
@Override
protected IASTProblem createProblem(int signal, int offset, int length) {
IASTProblem result = new CASTProblem(signal, EMPTY_STRING, true);
IASTProblem result = new CASTProblem(signal, CharArrayUtils.EMPTY, true);
((ASTNode) result).setOffsetAndLength(offset, length);
return result;
}
@ -2308,6 +2287,16 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
protected IASTAmbiguousExpression createAmbiguousExpression() {
return new CASTAmbiguousExpression();
}
@Override
protected IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr) {
return new CASTAmbiguousBinaryVsCastExpression(binary, castExpr);
}
@Override
protected IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall) {
return new CASTAmbiguousCastVsFunctionCallExpression(castExpr, funcCall);
}
protected IASTStatement parseIfStatement() throws EndOfFileException, BacktrackException {
IASTIfStatement result = null;

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2008 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.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousBinaryVsCastExpression;
public class CPPASTAmbiguousBinaryVsCastExpression extends ASTAmbiguousBinaryVsCastExpression {
public CPPASTAmbiguousBinaryVsCastExpression(IASTBinaryExpression bexp, IASTCastExpression castExpr) {
super(bexp, castExpr);
}
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2008 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.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousCastVsFunctionCallExpression;
public class CPPASTAmbiguousCastVsFunctionCallExpression extends ASTAmbiguousCastVsFunctionCallExpression {
public CPPASTAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall) {
super(castExpr, funcCall);
}
}

View file

@ -72,6 +72,7 @@ import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.IBinding;
@ -124,6 +125,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
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.IGNUASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember;
@ -830,39 +833,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
@Override
protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException {
IASTExpression firstExpression = pmExpression();
for (;;) {
switch (LT(1)) {
case IToken.tSTAR:
case IToken.tDIV:
case IToken.tMOD:
IToken t = consume();
IASTExpression secondExpression = pmExpression();
int operator = 0;
switch (t.getType()) {
case IToken.tSTAR:
operator = IASTBinaryExpression.op_multiply;
break;
case IToken.tDIV:
operator = IASTBinaryExpression.op_divide;
break;
case IToken.tMOD:
operator = IASTBinaryExpression.op_modulo;
break;
}
firstExpression = buildBinaryExpression(operator,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
default:
return firstExpression;
}
}
}
protected IASTExpression pmExpression() throws EndOfFileException, BacktrackException {
protected IASTExpression pmExpression() throws EndOfFileException, BacktrackException {
IASTExpression firstExpression = castExpression();
for (;;) {
switch (LT(1)) {
@ -1103,23 +1074,21 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
protected IASTExpression unaryExpression() throws EndOfFileException, BacktrackException {
switch (LT(1)) {
case IToken.tSTAR:
return unaryOperatorCastExpression(IASTUnaryExpression.op_star);// IASTExpression.Kind.UNARY_STAR_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_star);
case IToken.tAMPER:
return unaryOperatorCastExpression(IASTUnaryExpression.op_amper);// IASTExpression.Kind.UNARY_AMPSND_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_amper);
case IToken.tPLUS:
return unaryOperatorCastExpression(IASTUnaryExpression.op_plus);// IASTExpression.Kind.UNARY_PLUS_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_plus);
case IToken.tMINUS:
return unaryOperatorCastExpression(IASTUnaryExpression.op_minus);// IASTExpression.Kind.UNARY_MINUS_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_minus);
case IToken.tNOT:
return unaryOperatorCastExpression(IASTUnaryExpression.op_not);// IASTExpression.Kind.UNARY_NOT_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_not);
case IToken.tBITCOMPLEMENT:
return unaryOperatorCastExpression(IASTUnaryExpression.op_tilde);// IASTExpression.Kind.UNARY_TILDE_CASTEXPRESSION);
return unaryOperatorCastExpression(IASTUnaryExpression.op_tilde);
case IToken.tINCR:
return unaryOperatorCastExpression(IASTUnaryExpression.op_prefixIncr);// IASTExpression.Kind.UNARY_INCREMENT);
return unaryOperatorCastExpression(IASTUnaryExpression.op_prefixIncr);
case IToken.tDECR:
return unaryOperatorCastExpression(IASTUnaryExpression.op_prefixDecr);// IASTExpression.Kind.UNARY_DECREMENT);
case IToken.t_sizeof:
return parseSizeofExpression();
return unaryOperatorCastExpression(IASTUnaryExpression.op_prefixDecr);
case IToken.t_new:
return newExpression();
case IToken.t_delete:
@ -1133,17 +1102,16 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
default:
return postfixExpression();
}
case IToken.t_sizeof:
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof);
case IGCCToken.t_typeof:
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof);
case IGCCToken.t___alignof__:
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf);
default:
if (LT(1) == IGCCToken.t_typeof && supportTypeOfUnaries) {
IASTExpression unary = unaryTypeofExpression();
if (unary != null)
return unary;
}
if (LT(1) == IGCCToken.t___alignof__ && supportAlignOfUnaries) {
IASTExpression align = unaryAlignofExpression();
if (align != null)
return align;
}
return postfixExpression();
}
}
@ -1346,7 +1314,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return new CPPASTAmbiguousExpression();
}
protected ICPPASTAmbiguousTemplateArgument createAmbiguousTemplateArgument() {
@Override
protected IASTAmbiguousExpression createAmbiguousBinaryVsCastExpression(IASTBinaryExpression binary, IASTCastExpression castExpr) {
return new CPPASTAmbiguousBinaryVsCastExpression(binary, castExpr);
}
@Override
protected IASTAmbiguousExpression createAmbiguousCastVsFunctionCallExpression(IASTCastExpression castExpr, IASTFunctionCallExpression funcCall) {
return new CPPASTAmbiguousCastVsFunctionCallExpression(castExpr, funcCall);
}
protected ICPPASTAmbiguousTemplateArgument createAmbiguousTemplateArgument() {
return new CPPASTAmbiguousTemplateArgument();
}
@ -1358,7 +1336,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return new CPPASTTypenameExpression();
}
protected IASTFunctionCallExpression createFunctionCallExpression() {
@Override
protected IASTFunctionCallExpression createFunctionCallExpression() {
return new CPPASTFunctionCallExpression();
}
@ -1388,7 +1367,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return new CPPASTSimpleTypeConstructorExpression();
}
protected IASTExpression primaryExpression() throws EndOfFileException,
@Override
protected IASTExpression primaryExpression() throws EndOfFileException,
BacktrackException {
IToken t = null;
ICPPASTLiteralExpression literalExpression = null;
@ -1523,22 +1503,18 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
protected IASTExpression specialCastExpression(int kind) throws EndOfFileException, BacktrackException {
int startingOffset = LA(1).getOffset();
IToken op = consume();
final int offset = LA(1).getOffset();
final int optype= consume().getType();
consume(IToken.tLT);
IASTTypeId typeID = typeId(DeclarationOptions.TYPEID);
if (typeID == null) { throw backtrack; }
final IASTTypeId typeID = typeId(DeclarationOptions.TYPEID);
if (typeID == null)
throw backtrack;
consume(IToken.tGT);
consume(IToken.tLPAREN);
IASTExpression lhs = expression();
int l = consume(IToken.tRPAREN).getEndOffset();
IASTCastExpression result = createCastExpression();
((ASTNode) result).setOffsetAndLength(startingOffset, l - startingOffset);
result.setTypeId(typeID);
result.setOperand(lhs);
final IASTExpression operand= expression();
final int endOffset= consume(IToken.tRPAREN).getEndOffset();
int operator;
switch(op.getType()) {
switch(optype) {
case IToken.t_dynamic_cast:
operator = ICPPASTCastExpression.op_dynamic_cast;
break;
@ -1555,9 +1531,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
operator = IASTCastExpression.op_cast;
break;
}
result.setOperator(operator);
return result;
return buildCastExpression(operator, typeID, operand, offset, endOffset);
}
/**
@ -2825,7 +2799,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (encounteredRawType || encounteredTypename)
throwBacktrack(LA(1));
typeofExpression = unaryTypeofExpression();
final boolean wasInBinary= inBinaryExpression;
try {
inBinaryExpression= false;
typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof);
} finally {
inBinaryExpression= wasInBinary;
}
encounteredTypename= true;
endOffset= calculateEndOffset(typeofExpression);
break;
@ -4375,7 +4357,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
@Override
protected IASTProblem createProblem(int signal, int offset, int length) {
IASTProblem result = new CPPASTProblem(signal, EMPTY_STRING, true);
IASTProblem result = new CPPASTProblem(signal, CharArrayUtils.EMPTY, true);
((ASTNode) result).setOffsetAndLength(offset, length);
((ASTNode) result).setLength(length);
return result;

View file

@ -6,19 +6,22 @@
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM - Initial API and implementation
* IBM - Initial API and implementation
* Markus Schorn (Wind River Systems)
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier;
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
/**
* @author jcamelon
*/
public class GPPASTSimpleDeclSpecifier extends CPPASTSimpleDeclSpecifier
implements IGPPASTSimpleDeclSpecifier {
implements IGPPASTSimpleDeclSpecifier, IASTAmbiguityParent {
private boolean longLong;
private boolean restrict;
@ -100,4 +103,12 @@ public class GPPASTSimpleDeclSpecifier extends CPPASTSimpleDeclSpecifier
public void setImaginary(boolean value) {
this.imaginary = value;
}
public void replace(IASTNode child, IASTNode other) {
if (child == typeOfExpression) {
other.setPropertyInParent(child.getPropertyInParent());
other.setParent(child.getParent());
typeOfExpression= (IASTExpression) other;
}
}
}