diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index f50232bf7f2..3cdbd5bdac8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -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) & ab // 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()); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java index 46b745e3331..776430ce84e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTSignatureUtil.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousBinaryVsCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousBinaryVsCastExpression.java new file mode 100644 index 00000000000..0f1607677b8 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousBinaryVsCastExpression.java @@ -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 null, 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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousCastVsFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousCastVsFunctionCallExpression.java new file mode 100644 index 00000000000..03048ed0b85 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousCastVsFunctionCallExpression.java @@ -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 null, 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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java index cf97ed449a3..928bbc07e6d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/AbstractGNUSourceCodeParser.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousBinaryVsCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousBinaryVsCastExpression.java new file mode 100644 index 00000000000..80ac21af0c0 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousBinaryVsCastExpression.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousCastVsFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousCastVsFunctionCallExpression.java new file mode 100644 index 00000000000..15e972bed8a --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousCastVsFunctionCallExpression.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GCCASTSimpleDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GCCASTSimpleDeclSpecifier.java index 1a0f1b9b6ca..8ee8a38ba91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GCCASTSimpleDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GCCASTSimpleDeclSpecifier.java @@ -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; + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 49c95ff9a20..f8659bd6e24 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousBinaryVsCastExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousBinaryVsCastExpression.java new file mode 100644 index 00000000000..3e26049e014 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousBinaryVsCastExpression.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousCastVsFunctionCallExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousCastVsFunctionCallExpression.java new file mode 100644 index 00000000000..4645686d4f2 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousCastVsFunctionCallExpression.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 2da48e09f2c..3bd0bc62998 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GPPASTSimpleDeclSpecifier.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GPPASTSimpleDeclSpecifier.java index 80979ce3cea..1ced2ca22c3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GPPASTSimpleDeclSpecifier.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GPPASTSimpleDeclSpecifier.java @@ -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; + } + } }