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:
parent
803729074d
commit
076d4c7899
13 changed files with 984 additions and 293 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue