diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index 7f846c25f51..711b2a1c96c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -4395,7 +4395,8 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { // X<(1>2)> x2; // OK // template class Y { }; // Y< X<1> > x3; // OK - // Y> 1> > x4; // OK: Y< X< (6>>1) > > + // // with C++0x this is no longer valid: + // // Y> 1> > x4; // OK: Y< X< (6>>1) > > public void test14_2s3() throws Exception { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 5ff196dcd6b..fba9cb3f342 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTProblemStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.IBasicType; @@ -4245,4 +4246,58 @@ public class AST2TemplateTests extends AST2BaseTest { final String code= getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } + + // template class CT {}; + // template class CTI {}; + // + // int test() { + // int a; + // CT> x; + // a= 1 >> 2; + // return a; + // } + public void testClosingAngleBrackets1_261268() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } + + // template class CT {}; + // template class CTI {}; + // + // int test() { + // int a; + // a= 1 > > 3; // must be syntax error + // return a; + // } + public void testClosingAngleBrackets2_261268() throws Exception { + final String code= getAboveComment(); + IASTTranslationUnit tu = parse(code, ParserLanguage.CPP, true, false); + IASTFunctionDefinition fdef= getDeclaration(tu, 2); + IASTProblemStatement p1= getStatement(fdef, 1); + } + + // template class CT {}; + // typedef int TInt; + // int test() { + // int a; + // CT> x; // declaration + // int y= a> a; // binary expression + // a> a; // binary expression via ambiguity + // y= a < a >> (1+2); // binary expression + // a < a >> (1+2); // binary expression via ambiguity + // } + public void testClosingAngleBracketsAmbiguity_261268() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } + + // #define OPASSIGN(x) x##= + // int test() { + // int a=1; + // a OPASSIGN(>>) 1; + // } + public void testTokenPasteShiftROperaotr_261268() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } 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 548a5785952..9dbe8961888 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 @@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; import org.eclipse.cdt.core.dom.ast.IASTCastExpression; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; +import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; @@ -33,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDoStatement; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpressionList; import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; import org.eclipse.cdt.core.dom.ast.IASTFieldReference; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; @@ -5434,6 +5436,59 @@ public class AST2Tests extends AST2BaseTest { } } + // int a,b; + // void test() { + + // 1+2+3 // 1,2,+,3,+ + // a=b=1 // a,b,1,=,= + // 0, a= 1 ? 2,3 : b= 4, 5 // 0,a,1,2,3,,,b,4,=,?,=,5,, + // 1 ? 2 ? 3 : 4 ? 5 : 6 : 7 // 1,2,3,4,5,6,?,?,7,? + public void testBinaryExpressionBinding() 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, 1); + IASTExpression expr= getExpressionOfStatement(fdef, 0); + assertEquals("expr: " + exprStr, io[1].trim(), polnishNotation(expr)); + assertEquals(exprStr, expr.getRawSignature()); + checkOffsets(exprStr, expr); + } + } + } + + // int a,b; + // void test(int a= + + // 1+2+3 // 1,2,+,3,+ + // a=b=1 // a,b,1,=,= + // 1 ? 2,3 : b= 4 // 1,2,3,,,b,4,=,? + // 1 ? 2 ? 3 : 4 ? 5 : 6 : 7 // 1,2,3,4,5,6,?,?,7,? + public void testConstantExpressionBinding() 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, 1); + IASTFunctionDeclarator fdtor= fdef.getDeclarator(); + IASTParameterDeclaration pdecl= (IASTParameterDeclaration) fdtor.getChildren()[1]; + IASTExpression expr= ((IASTInitializerExpression) pdecl.getDeclarator().getInitializer()).getExpression(); + 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; @@ -5484,7 +5539,24 @@ public class AST2Tests extends AST2BaseTest { } private void polnishNotation(IASTExpression expr, StringBuilder buf) { - if (expr instanceof IASTBinaryExpression) { + if (expr instanceof IASTConditionalExpression) { + IASTConditionalExpression bexpr= (IASTConditionalExpression) expr; + polnishNotation(bexpr.getLogicalConditionExpression(), buf); + buf.append(','); + polnishNotation(bexpr.getPositiveResultExpression(), buf); + buf.append(','); + polnishNotation(bexpr.getNegativeResultExpression(), buf); + buf.append(','); + buf.append('?'); + } else if (expr instanceof IASTExpressionList) { + IASTExpressionList bexpr= (IASTExpressionList) expr; + IASTExpression[] args = bexpr.getExpressions(); + for (IASTExpression e : args) { + polnishNotation(e, buf); + buf.append(','); + } + buf.append(','); + } else if (expr instanceof IASTBinaryExpression) { IASTBinaryExpression bexpr= (IASTBinaryExpression) expr; polnishNotation(bexpr.getOperand1(), buf); buf.append(','); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java index 274c615eee5..e37c2baf261 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IScanner.java @@ -68,12 +68,11 @@ public interface IScanner { public void setContentAssistMode(int offset); /** - * Method has no effect. + * Instructs the scanner to split tokens of kind {@link IToken#tSHIFTR} into two tokens of + * kind {@link IToken#tGT_in_SHIFTR}. * @noreference This method is not intended to be referenced by clients. - * @since 4.0 */ - @Deprecated - public void setScanComments(boolean val); + public void setSplitShiftROperator(boolean val); /** * Turns on/off creation of image locations. @@ -106,4 +105,10 @@ public interface IScanner { * @noreference This method is not intended to be referenced by clients. */ public int getCodeBranchNesting(); + + /** + * @noreference This method is not intended to be referenced by clients. + */ + @Deprecated + public void setScanComments(boolean val); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java index 6bdd02b95b6..5c90dcad839 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IToken.java @@ -94,7 +94,11 @@ public interface IToken { int tDOT = 50; int tDIVASSIGN = 51; int tDIV = 52; - + /** + * @see IScanner#setSplitShiftROperator(boolean) + * @since 5.2 + */ + int tGT_in_SHIFTR= 53; /** @deprecated use {@link #tAND} */ @Deprecated int t_and = 54; /** @deprecated use {@link #tAMPERASSIGN} */ @Deprecated int t_and_eq = 55; int t_asm = 56; 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 7a1355f727d..ab17c905e69 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 @@ -147,6 +147,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return PROCESS_CONTINUE; } }; + + /** + * Information about the context in which a cast-expression is parsed: + * in a binary expression, in a binary expression in a template-id, or elsewhere. + */ + protected static enum CastExprCtx {eBExpr, eBExprInTmplID, eNotBExpr} + protected static enum ExprKind {eExpression, eAssignment, eConstant} protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4; protected static int parseCount = 0; @@ -184,7 +191,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected BacktrackException backtrack = new BacktrackException(); protected ASTCompletionNode completionNode; - protected IASTTypeId fTypeIdForCastAmbiguity; private final INodeFactory nodeFactory; private boolean fActiveCode= true; @@ -269,12 +275,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } private final IToken nextToken(boolean skipInactive) throws EndOfFileException { - IToken t= nextToken; - if (t == null) { - t= fetchToken(skipInactive); - } - nextToken= t; - return t; + final IToken t= nextToken; + if (t != null) + return t; + + final IToken tn= fetchToken(skipInactive); + nextToken= tn; + return tn; } private final IToken lookaheadToken(int i, boolean skipInactive) throws EndOfFileException { @@ -457,6 +464,18 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return result; } + /** + * If the type of the next token matches, it is consumed and returned. Otherwise a + * {@link BacktrackException} will be thrown. + */ + protected final IToken consume(int type1, int type2) throws EndOfFileException, BacktrackException { + final IToken result= consume(); + final int lt1 = result.getType(); + if (lt1 != type1 && lt1 != type2) + throwBacktrack(result); + return result; + } + /** * Consume the next token available only if the type is as specified. In case we reached the end of * completion, no token is consumed and the eoc-token returned. @@ -884,125 +903,71 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { * Models a cast expression followed by an operator. Can be linked into a chain. * This is done right to left, such that a tree of variants can be built. */ - protected static class CastExpressionOp { - final CastExpressionOp fLeft; - final IASTExpression fExpression; + protected static class BinaryOperator { final int fOperatorToken; final int fLeftPrecedence; final int fRightPrecedence; + BinaryOperator fNext; + IASTExpression fExpression; + final CastAmbiguityMarker fAmbiguityMarker; - public CastExpressionOp(CastExpressionOp left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) { - fLeft= left; - fExpression= expression; + public BinaryOperator(BinaryOperator left, IASTExpression expression, int operatorToken, int leftPrecedence, int rightPrecedence) { + fNext= left; fOperatorToken= operatorToken; fLeftPrecedence= leftPrecedence; fRightPrecedence= rightPrecedence; + if (expression instanceof CastAmbiguityMarker) { + fAmbiguityMarker= (CastAmbiguityMarker) expression; + fExpression= fAmbiguityMarker.fExpression; + fAmbiguityMarker.fExpression= null; + } else { + fExpression= expression; + fAmbiguityMarker= null; + } + } + + public IASTExpression exchange(IASTExpression expr) { + IASTExpression e= fExpression; + fExpression= expr; + return e; } } - /** - * Helper class to temporarily store a sequence of operator followed by expression. - */ - private static final class OpCastExpressionStack { - private IASTExpression fExpressions[]= new IASTExpression[128]; - private int fPrecedenceAndTokens[]= new int[256]; - private int fPos=-1; - - boolean isEmpty() { - return fPos<0; - } - - public IASTExpression getExpression() { - return fExpressions[fPos]; - } - - public int getLeftPrecedence() { - return fPrecedenceAndTokens[2*fPos]; - } - - public int getOperatorToken() { - return fPrecedenceAndTokens[2*fPos+1]; - } - - public void push(int leftPrecedence, int operatorToken, IASTExpression trailing) { - final int pos= ++fPos; - if (pos == fExpressions.length) { - IASTExpression newExpressions[]= new IASTExpression[pos*2]; - int newPrecedenceAndTokens[]= new int[pos*4]; - System.arraycopy(fExpressions, 0, newExpressions, 0, pos); - System.arraycopy(fPrecedenceAndTokens, 0, newPrecedenceAndTokens, 0, 2*pos); - fExpressions= newExpressions; - fPrecedenceAndTokens= newPrecedenceAndTokens; + protected final IASTExpression buildExpression(BinaryOperator leftChain, IASTExpression expr) throws BacktrackException { + BinaryOperator rightChain= null; + for (;;) { + if (leftChain == null) { + if (rightChain == null) + return expr; + + expr= buildExpression(expr, rightChain); + rightChain= rightChain.fNext; + } else if (rightChain != null && leftChain.fRightPrecedence < rightChain.fLeftPrecedence) { + expr= buildExpression(expr, rightChain); + rightChain= rightChain.fNext; + } else { + BinaryOperator op= leftChain; + leftChain= leftChain.fNext; + expr= op.exchange(expr); + op.fNext= rightChain; + rightChain= op; } - - fExpressions[pos]= trailing; - fPrecedenceAndTokens[2*pos]= leftPrecedence; - fPrecedenceAndTokens[2*pos+1]= operatorToken; - } - - public void pop() { - --fPos; } } - protected final IASTExpression buildExpression(CastExpressionOp exprOp1, IASTExpression expr) throws BacktrackException { - if (exprOp1 == null) - return expr; - - // exprOp1 exprOp2 expr - CastExpressionOp exprOp2= exprOp1; - exprOp1= exprOp1.fLeft; - OpCastExpressionStack stack= null; - - while (exprOp1 != null) { - if (exprOp1.fRightPrecedence < exprOp2.fLeftPrecedence) { - // (exprOp2 expr) -> expr2 - expr= buildExpression(exprOp2.fExpression, exprOp2.fOperatorToken, expr, stack); - if (stack != null) { - while (!stack.isEmpty() && exprOp1.fRightPrecedence < stack.getLeftPrecedence()) { - final int opToken= stack.getOperatorToken(); - final IASTExpression expr2= stack.getExpression(); - stack.pop(); - expr= buildExpression(expr, opToken, expr2, stack); - } - } - } else { - // expr(Op2 expr) -> expr | op2 expr on stack - if (stack == null) { - stack= new OpCastExpressionStack(); - } - stack.push(exprOp2.fLeftPrecedence, exprOp2.fOperatorToken, expr); - expr= exprOp2.fExpression; - } - exprOp2= exprOp1; - exprOp1= exprOp1.fLeft; - } - - // (exprOp2 expr) -> expr2 - expr= buildExpression(exprOp2.fExpression, exprOp2.fOperatorToken, expr, stack); - if (stack != null) { - while (!stack.isEmpty()) { - final int opToken= stack.getOperatorToken(); - final IASTExpression expr2= stack.getExpression(); - stack.pop(); - expr= buildExpression(expr, opToken, expr2, stack); - } - } - return expr; - } - - private IASTExpression buildExpression(IASTExpression left, int token, IASTExpression right, OpCastExpressionStack stack) throws BacktrackException { - int op, unaryOp=0; - switch(token) { + private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) throws BacktrackException { + int op, unaryOp= 0; + final IASTExpression right= operator.fExpression; + switch(operator.fOperatorToken) { case IToken.tQUESTION: - if (stack == null || stack.isEmpty() || stack.getOperatorToken() != IToken.tCOLON) { + if (operator.fNext == null || operator.fNext.fOperatorToken != IToken.tCOLON) { assert false; ASTNode node= (ASTNode) left; throwBacktrack(node.getOffset(), node.getLength()); return null; // Will never be reached. } - IASTExpression negative= stack.getExpression(); - stack.pop(); + IASTExpression negative= operator.fNext.fExpression; + operator.fNext= operator.fNext.fNext; IASTConditionalExpression conditionalEx = nodeFactory.newConditionalExpession(left, right, negative); setRange(conditionalEx, left); if (negative != null) { @@ -1134,35 +1099,20 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return null; } - CastAmbiguityMarker lca= null; - CastAmbiguityMarker rca= null; - if (left instanceof CastAmbiguityMarker) { - lca= (CastAmbiguityMarker) left; - left= lca.getExpression(); - assert !(left instanceof CastAmbiguityMarker); - } - if (right instanceof CastAmbiguityMarker) { - rca= (CastAmbiguityMarker) right; - right= rca.getExpression(); - assert !(right instanceof CastAmbiguityMarker); - } - IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right)); - - if (lca != null) { + final CastAmbiguityMarker am = operator.fAmbiguityMarker; + if (am != null) { assert unaryOp != 0; result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result, - lca.getTypeIdForCast(), unaryOp, lca.getUnaryOperatorOffset()); + am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset()); } - - return rca == null ? result : rca.updateExpression(result); + return result; } protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException; - protected abstract IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException; protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException; - protected abstract IASTExpression unaryExpression(boolean inBinary) throws BacktrackException, EndOfFileException; - protected abstract IASTExpression primaryExpression() throws BacktrackException, EndOfFileException; + protected abstract IASTExpression unaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException; + protected abstract IASTExpression primaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException; protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException; private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression { @@ -1202,7 +1152,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } } - protected final IASTExpression castExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException { + protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { if (LT(1) == IToken.tLPAREN) { final IToken mark= mark(); final int startingOffset= mark.getOffset(); @@ -1211,7 +1161,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { if (typeId != null && LT(1) == IToken.tRPAREN) { consume(); boolean unaryFailed= false; - if (inBinaryExpression) { + if (ctx != CastExprCtx.eNotBExpr) { switch (LT(1)){ // ambiguity with unary operator case IToken.tPLUS: case IToken.tMINUS: @@ -1220,7 +1170,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { IToken markEnd= mark(); backup(mark); try { - IASTExpression unary= unaryExpression(false); + IASTExpression unary= unaryExpression(CastExprCtx.eNotBExpr); return new CastAmbiguityMarker(unary, typeId, operatorOffset); } catch (BacktrackException bt) { backup(markEnd); @@ -1230,7 +1180,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } try { boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN; - IASTExpression rhs= castExpression(inBinaryExpression); + IASTExpression rhs= castExpression(ctx); CastAmbiguityMarker ca= null; if (rhs instanceof CastAmbiguityMarker) { @@ -1243,7 +1193,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { IToken markEnd= mark(); backup(mark); try { - IASTExpression expr= primaryExpression(); + IASTExpression expr= primaryExpression(ctx); IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, null); IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall); ((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result); @@ -1261,7 +1211,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } backup(mark); } - return unaryExpression(inBinaryExpression); + return unaryExpression(ctx); } protected abstract IASTTranslationUnit getTranslationUnit(); @@ -1386,9 +1336,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { return result; } - protected IASTExpression unarayExpression(int operator, boolean inBinary) throws EndOfFileException, BacktrackException { + protected IASTExpression unaryExpression(int operator, CastExprCtx ctx) throws EndOfFileException, BacktrackException { final IToken operatorToken= consume(); - IASTExpression operand= castExpression(inBinary); + IASTExpression operand= castExpression(ctx); CastAmbiguityMarker ca= null; if (operand instanceof CastAmbiguityMarker) { @@ -2185,7 +2135,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { } protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis, - int offset, int typeExprKind, int unaryExprKind, boolean inBinary) throws BacktrackException, EndOfFileException { + int offset, int typeExprKind, int unaryExprKind, CastExprCtx ctx) throws BacktrackException, EndOfFileException { IASTTypeId typeid; IASTExpression expr= null; IToken typeidLA= null; @@ -2246,7 +2196,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { expr= expression(); endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset(); } else { - expr= unaryExpression(inBinary); + expr= unaryExpression(ctx); if (expr instanceof CastAmbiguityMarker) { ca= (CastAmbiguityMarker) expr; expr= ca.getExpression(); 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 4dbecbc0c78..5f775f2fbae 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 @@ -145,7 +145,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { protected IASTInitializer cInitializerClause(boolean inAggregate) throws EndOfFileException, BacktrackException { final int offset = LA(1).getOffset(); if (LT(1) != IToken.tLBRACE) { - IASTExpression assignmentExpression= assignmentExpression(); + IASTExpression assignmentExpression= expression(ExprKind.eAssignment); if (inAggregate && skipTrivialExpressionsInAggregateInitializers) { if (!ASTQueries.canContainName(assignmentExpression)) return null; @@ -446,32 +446,29 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { @Override protected IASTExpression expression() throws BacktrackException, EndOfFileException { - return expression(true, true); + return expression(ExprKind.eExpression); } - @Override - protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException { - return expression(false, true); - } - @Override protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException { - return expression(false, false); + return expression(ExprKind.eConstant); } - private IASTExpression expression(boolean allowComma, boolean allowAssignment) throws BacktrackException, EndOfFileException { + private IASTExpression expression(final ExprKind kind) throws EndOfFileException, BacktrackException { + final boolean allowComma= kind==ExprKind.eExpression; + boolean allowAssignment= kind !=ExprKind.eConstant; int lt1; int conditionCount= 0; - CastExpressionOp lastComponent= null; - IASTExpression lastExpression= castExpression(true); + BinaryOperator lastOperator= null; + IASTExpression lastExpression= castExpression(CastExprCtx.eBExpr); loop: while(true) { lt1= LT(1); switch(lt1) { case IToken.tQUESTION: conditionCount++; // ? : - // Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 25, 1); + // Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 25, 0); if (LT(2) == IToken.tCOLON) { // Gnu extension: The expression after '?' can be omitted. consume(); // Consume operator @@ -487,7 +484,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { // ? : // Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment; - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 0, 15); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 0, 15); allowAssignment= true; // assignment expressions will be subsumed by the conditional expression break; @@ -495,7 +492,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (!allowComma && conditionCount == 0) break loop; // Lowest precedence except inside the conditional expression - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 10, 11); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 10, 11); break; case IToken.tASSIGN: @@ -512,27 +509,27 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (!allowAssignment && conditionCount == 0) break loop; // Assignments group right to left - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 21, 20); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 21, 20); break; case IToken.tOR: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 30, 31); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 30, 31); break; case IToken.tAND: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 40, 41); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 40, 41); break; case IToken.tBITOR: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 50, 51); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 50, 51); break; case IToken.tXOR: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 60, 61); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 60, 61); break; case IToken.tAMPER: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 70, 71); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 70, 71); break; case IToken.tEQUAL: case IToken.tNOTEQUAL: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 80, 81); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 80, 81); break; case IToken.tGT: case IToken.tLT: @@ -540,70 +537,70 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { case IToken.tGTEQUAL: case IGCCToken.tMAX: case IGCCToken.tMIN: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 90, 91); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 90, 91); break; case IToken.tSHIFTL: case IToken.tSHIFTR: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 100, 101); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 100, 101); break; case IToken.tPLUS: case IToken.tMINUS: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 110, 111); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 110, 111); break; case IToken.tSTAR: case IToken.tDIV: case IToken.tMOD: - lastComponent= new CastExpressionOp(lastComponent, lastExpression, lt1, 120, 121); + lastOperator= new BinaryOperator(lastOperator, lastExpression, lt1, 120, 121); break; default: break loop; } - consume(); // consume operator - lastExpression= castExpression(true); // next cast expression + consume(); // consume operator + lastExpression= castExpression(CastExprCtx.eBExpr); // next cast expression } // Check for incomplete conditional expression if (lt1 != IToken.tEOC && conditionCount > 0) throwBacktrack(LA(1)); - return buildExpression(lastComponent, lastExpression); + return buildExpression(lastOperator, lastExpression); } @Override - protected IASTExpression unaryExpression(boolean inBinary) throws EndOfFileException, BacktrackException { + protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { switch (LT(1)) { case IToken.tSTAR: - return unarayExpression(IASTUnaryExpression.op_star, inBinary); + return unaryExpression(IASTUnaryExpression.op_star, ctx); case IToken.tAMPER: - return unarayExpression(IASTUnaryExpression.op_amper, inBinary); + return unaryExpression(IASTUnaryExpression.op_amper, ctx); case IToken.tPLUS: - return unarayExpression(IASTUnaryExpression.op_plus, inBinary); + return unaryExpression(IASTUnaryExpression.op_plus, ctx); case IToken.tMINUS: - return unarayExpression(IASTUnaryExpression.op_minus, inBinary); + return unaryExpression(IASTUnaryExpression.op_minus, ctx); case IToken.tNOT: - return unarayExpression(IASTUnaryExpression.op_not, inBinary); + return unaryExpression(IASTUnaryExpression.op_not, ctx); case IToken.tBITCOMPLEMENT: - return unarayExpression(IASTUnaryExpression.op_tilde, inBinary); + return unaryExpression(IASTUnaryExpression.op_tilde, ctx); case IToken.tINCR: - return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinary); + return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx); case IToken.tDECR: - return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinary); + return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx); case IToken.t_sizeof: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinary); + IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx); case IGCCToken.t_typeof: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinary); + IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx); case IGCCToken.t___alignof__: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinary); + IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx); default: - return postfixExpression(); + return postfixExpression(ctx); } } - protected IASTExpression postfixExpression() throws EndOfFileException, BacktrackException { + protected IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { IASTExpression firstExpression = null; switch (LT(1)) { case IToken.tLPAREN: @@ -625,11 +622,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } catch (BacktrackException bt) { } backup(m); - firstExpression= primaryExpression(); + firstExpression= primaryExpression(ctx); break; default: - firstExpression = primaryExpression(); + firstExpression = primaryExpression(ctx); break; } @@ -719,7 +716,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { } @Override - protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException { + protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { IToken t = null; IASTLiteralExpression literalExpression = null; switch (LT(1)) { @@ -755,7 +752,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { return compoundStatementExpression(); } t = consume(); - IASTExpression lhs = expression(true, true); // instead of expression(), to keep the stack smaller + IASTExpression lhs = expression(ExprKind.eExpression); // instead of expression(), to keep the stack smaller int finalOffset = 0; switch (LT(1)) { case IToken.tRPAREN: @@ -1085,7 +1082,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(LA(1)); typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false); + IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr); encounteredTypename= true; endOffset= calculateEndOffset(typeofExpression); @@ -1705,7 +1702,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { if (LT(1) != IToken.tRBRACKET) { if (!(isStatic || isRestrict || isConst || isVolatile)) - exp = assignmentExpression(); + exp = expression(ExprKind.eAssignment); else exp = constantExpression(); } 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 118bd1ffb09..65245d5acf4 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 @@ -150,7 +150,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { protected ICPPASTTranslationUnit translationUnit; private int functionBodyCount= 0; - private int rejectLogicalOperatorInTemplateID= 0; private char[] currentClassName; private final ICPPNodeFactory nodeFactory; @@ -181,6 +180,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { functionCallCanBeLValue= true; this.index= index; this.nodeFactory = CPPNodeFactory.getDefault(); + scanner.setSplitShiftROperator(true); } @Override @@ -195,15 +195,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throw backtrack; } - protected IASTName idExpression() throws EndOfFileException, BacktrackException { - try { - rejectLogicalOperatorInTemplateID++; - return qualifiedName(); - } finally { - rejectLogicalOperatorInTemplateID--; - } - } - /** * Parse a name. * name ::= ("::")? name2 ("::" name2)* @@ -211,7 +202,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * * @throws BacktrackException request a backtrack */ - private IASTName qualifiedName() throws BacktrackException, EndOfFileException { + private IASTName qualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException { ICPPASTQualifiedName qname= null; IASTName name= null; final int offset= LA(1).getOffset(); @@ -261,7 +252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } haveName= true; - name= addTemplateArguments(name); + name= addTemplateArguments(name, ctx); endOffset= calculateEndOffset(name); if (qname != null) { qname.addName(name); @@ -309,24 +300,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return name; } - private IASTName addTemplateArguments(IASTName templateName) throws EndOfFileException, BacktrackException { - if (!canBeTemplateArguments()) - return templateName; + private IASTName addTemplateArguments(IASTName templateName, CastExprCtx ctx) throws EndOfFileException, BacktrackException { + boolean isAmbiguous= false; + switch(canBeTemplateArguments(ctx)) { + case -1: + return templateName; + case 0: + isAmbiguous= true; + break; + } IToken secondMark = mark(); consume(IToken.tLT); try { - // bug 229062: content assist after '<' needs to prefer to backtrack here - if (rejectLogicalOperatorInTemplateID == 1) { - final int lt1= LT(1); - if (lt1 == IToken.tCOMPLETION || lt1 == IToken.tEOC) { - throw backtrack; - } - } - - List list = templateArgumentList(); + List list = templateArgumentList(isAmbiguous); IToken end= LA(1); switch(end.getType()) { + case IToken.tGT_in_SHIFTR: case IToken.tGT: consume(); break; @@ -360,34 +350,109 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { /** * Makes a fast check whether there could be template arguments. */ - private boolean canBeTemplateArguments() throws EndOfFileException, BacktrackException { + private int canBeTemplateArguments(CastExprCtx ctx) throws EndOfFileException, BacktrackException { if (LTcatchEOF(1) != IToken.tLT) - return false; - + return -1; + final IToken mark= mark(); try { consume(); int nk= 0; int depth= 0; int angleDepth= 0; - int limit= 100; + int limit= 10000; while(--limit > 0) { switch(consume().getType()) { case IToken.tEOC: case IToken.tCOMPLETION: - return true; + return ctx == CastExprCtx.eNotBExpr ? 0 : -1; case IToken.tLT: if (nk == 0) { angleDepth++; } break; + case IToken.tGT_in_SHIFTR: case IToken.tGT: if (nk == 0) { if (--angleDepth < 0) { - final int lt1= LTcatchEOF(1); - return (lt1 != IToken.tINTEGER && lt1 != IToken.tFLOATINGPT); + if (ctx == CastExprCtx.eNotBExpr) + return 1; + + int lt1= LTcatchEOF(1); + if (lt1 == IToken.tGT_in_SHIFTR) { + if (ctx != CastExprCtx.eBExprInTmplID) + return -1; + // do the same check for the enclosing template + lt1= LTcatchEOF(2); + } + switch(lt1) { + // can be some cast-expression or continuation after template-id + case IToken.tCOLONCOLON: // CT::member + case IToken.tLPAREN: // ft(args) + return 0; + // end of an expression + // unary expression + case IToken.tMINUS: + case IToken.tPLUS: + case IToken.tAMPER: + case IToken.tSTAR: + case IToken.tNOT: + case IToken.tBITCOMPLEMENT: + case IToken.tINCR: + case IToken.tDECR: + case IToken.t_new: + case IToken.t_delete: + case IToken.t_sizeof: + case IGCCToken.t_typeof: + case IGCCToken.t___alignof__: + // postfix expression + case IToken.t_typename: + case IToken.t_char: + case IToken.t_wchar_t: + case IToken.t_bool: + case IToken.t_short: + case IToken.t_int: + case IToken.t_long: + case IToken.t_signed: + case IToken.t_unsigned: + case IToken.t_float: + case IToken.t_double: + case IToken.t_dynamic_cast: + case IToken.t_static_cast: + case IToken.t_reinterpret_cast: + case IToken.t_const_cast: + case IToken.t_typeid: + // primary expression + case IToken.tINTEGER: + case IToken.tFLOATINGPT: + case IToken.tSTRING: + case IToken.tLSTRING: + case IToken.tUTF16STRING: + case IToken.tUTF32STRING: + case IToken.tCHAR: + case IToken.tLCHAR: + case IToken.tUTF16CHAR: + case IToken.tUTF32CHAR: + case IToken.t_false: + case IToken.t_true: + case IToken.t_this: + case IToken.tIDENTIFIER: + case IToken.t_operator: + case IToken.tCOMPLETION: + return -1; + // ending an expression + case IToken.tSEMI: + case IToken.tCOMMA: + case IToken.tRBRACE: + case IToken.tRBRACKET: + case IToken.tRPAREN: + return 1; + // don't know + default: + return 0; + } } } break; @@ -426,31 +491,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.tLBRACE: case IToken.tRBRACE: if (nk == 0) { - return false; + return -1; } break; } } - return true; + return 0; } finally { backup(mark); } } - private List templateArgumentList() throws EndOfFileException, BacktrackException { + private List templateArgumentList(boolean isAmbiguous) throws EndOfFileException, BacktrackException { IToken start = LA(1); int startingOffset = start.getOffset(); int endOffset = 0; start = null; List list = new ArrayList(); + final BinaryExprCtx exprCtx = isAmbiguous ? BinaryExprCtx.eAmbigTmplID : BinaryExprCtx.eTmplID; boolean failed = false; - - while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) { + int lt1= LT(1); + while (lt1 != IToken.tGT && lt1 != IToken.tGT_in_SHIFTR && lt1 != IToken.tEOC) { IToken argStart = mark(); IASTTypeId typeId = typeId(DeclarationOptions.TYPEID); - if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) { + lt1 = LT(1); + if(typeId != null && (lt1==IToken.tCOMMA || lt1==IToken.tGT || lt1 == IToken.tGT_in_SHIFTR || lt1==IToken.tEOC)) { // potentially a type-id - check for id-expression ambiguity IToken typeIdEnd= mark(); try { @@ -470,7 +537,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throw backtrack; backup(argStart); - IASTExpression expression = expression(false, true, true); + IASTExpression expression = expression(ExprKind.eAssignment, exprCtx); if (expression instanceof IASTIdExpression) { if (mark() != typeIdEnd) throw backtrack; @@ -491,13 +558,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } else { // not a type-id - try as expression backup(argStart); - IASTExpression expression = expression(false, true, true); + IASTExpression expression = expression(ExprKind.eAssignment, exprCtx); list.add(expression); } - if (LT(1) == IToken.tCOMMA) { + lt1= LT(1); + if (lt1 == IToken.tCOMMA) { consume(); - } else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) { + lt1= LT(1); + } else if (lt1 != IToken.tGT && lt1 != IToken.tGT_in_SHIFTR && lt1 != IToken.tEOC) { failed = true; endOffset = LA(1).getEndOffset(); break; @@ -539,6 +608,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { op= OverloadableOperator.valueOf(t); } break; + case IToken.tGT_in_SHIFTR: + consume(); + endOffset= consume(IToken.tGT_in_SHIFTR).getEndOffset(); + op= OverloadableOperator.SHIFTR; + break; default: op= OverloadableOperator.valueOf(LA(1)); if (op != null) { @@ -564,30 +638,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return name; } + /** + * Information for the parser, whether a binary expression is parsed in the context of a + * template-id an ambiguous template-id (one where the '<' could be a greater sign) or + * else where. + */ + private enum BinaryExprCtx {eTmplID, eAmbigTmplID, eNoTmplID} + @Override protected IASTExpression expression() throws BacktrackException, EndOfFileException { - return expression(true, true, false); + return expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID); } - @Override - protected IASTExpression assignmentExpression() throws EndOfFileException, BacktrackException { - return expression(false, true, false); - } - @Override protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException { - return expression(false, false, false); + return expression(ExprKind.eConstant, BinaryExprCtx.eNoTmplID); } - private IASTExpression expression(boolean allowComma, boolean allowAssignment, boolean onTopOfTemplateArgs) throws EndOfFileException, BacktrackException { + private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx) throws EndOfFileException, BacktrackException { + final boolean allowComma= kind==ExprKind.eExpression; + boolean allowAssignment= kind !=ExprKind.eConstant; + final CastExprCtx castCtx= ctx == BinaryExprCtx.eNoTmplID ? CastExprCtx.eBExpr : CastExprCtx.eBExprInTmplID; + if (allowAssignment && LT(1) == IToken.t_throw) { return throwExpression(); } int lt1; int conditionCount= 0; - CastExpressionOp lastComponent= null; - IASTExpression expr= castExpression(true); + BinaryOperator lastOperator= null; + IASTExpression expr= castExpression(castCtx); loop: while(true) { // typically after a binary operator there cannot be a throw expression @@ -595,13 +675,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { lt1= LT(1); switch(lt1) { case IToken.tQUESTION: - if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) { + if (ctx == BinaryExprCtx.eAmbigTmplID) { throwBacktrack(LA(1)); } conditionCount++; // ? : - // Precedence: 25 is lower than precedence of logical or; 1 is lower than precedence of expression - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 25, 1); + // Precedence: 25 is lower than precedence of logical or; 0 is lower than precedence of expression + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 25, 0); if (LT(2) == IToken.tCOLON) { // Gnu extension: The expression after '?' can be omitted. consume(); // Consume operator @@ -618,7 +698,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // ? : // Precedence: 0 is lower than precedence of expression; 15 is lower than precedence of assignment; - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 0, 15); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 0, 15); allowAssignment= true; // assignment expressions will be subsumed by the conditional expression allowThrow= true; break; @@ -628,7 +708,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (!allowComma && conditionCount == 0) break loop; // Lowest precedence except inside the conditional expression - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 10, 11); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 10, 11); break; case IToken.tASSIGN: @@ -645,36 +725,36 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (!allowAssignment && conditionCount == 0) break loop; // Assignments group right to left - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 21, 20); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 21, 20); break; case IToken.tOR: - if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) { + if (ctx == BinaryExprCtx.eAmbigTmplID) { throwBacktrack(LA(1)); } - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 30, 31); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 30, 31); break; case IToken.tAND: - if (onTopOfTemplateArgs && rejectLogicalOperatorInTemplateID > 0) { + if (ctx == BinaryExprCtx.eAmbigTmplID) { throwBacktrack(LA(1)); } - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 40, 41); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 40, 41); break; case IToken.tBITOR: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 50, 51); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 50, 51); break; case IToken.tXOR: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 60, 61); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 60, 61); break; case IToken.tAMPER: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 70, 71); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 70, 71); break; case IToken.tEQUAL: case IToken.tNOTEQUAL: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 80, 81); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 80, 81); break; case IToken.tGT: - if (onTopOfTemplateArgs) + if (ctx != BinaryExprCtx.eNoTmplID) break loop; //$FALL-THROUGH$ case IToken.tLT: @@ -682,24 +762,33 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.tGTEQUAL: case IGCCToken.tMAX: case IGCCToken.tMIN: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 90, 91); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 90, 91); break; - case IToken.tSHIFTL: + case IToken.tGT_in_SHIFTR: + if (ctx != BinaryExprCtx.eNoTmplID) + break loop; + if (LT(2) != IToken.tGT_in_SHIFTR) { + throwBacktrack(LA(1)); + } + lt1= IToken.tSHIFTR; // convert back + consume(); // consume the extra token + //$FALL-THROUGH$ + case IToken.tSHIFTL: case IToken.tSHIFTR: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 100, 101); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 100, 101); break; case IToken.tPLUS: case IToken.tMINUS: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 110, 111); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 110, 111); break; case IToken.tSTAR: case IToken.tDIV: case IToken.tMOD: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 120, 121); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 120, 121); break; case IToken.tDOTSTAR: case IToken.tARROWSTAR: - lastComponent= new CastExpressionOp(lastComponent, expr, lt1, 130, 131); + lastOperator= new BinaryOperator(lastOperator, expr, lt1, 130, 131); break; default: break loop; @@ -716,14 +805,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { break loop; } } - expr= castExpression(true); // next cast expression + expr= castExpression(castCtx); // next cast expression } // Check for incomplete conditional expression if (lt1 != IToken.tEOC && conditionCount > 0) throwBacktrack(LA(1)); - return buildExpression(lastComponent, expr); + return buildExpression(lastOperator, expr); } private IASTExpression throwExpression() throws EndOfFileException, BacktrackException { @@ -759,7 +848,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(IToken.tRBRACKET); vectored = true; } - IASTExpression castExpression = castExpression(false); + IASTExpression castExpression = castExpression(CastExprCtx.eNotBExpr); ICPPASTDeleteExpression deleteExpression = nodeFactory.newDeleteExpression(castExpression); ((ASTNode) deleteExpression).setOffsetAndLength(startingOffset, calculateEndOffset(castExpression) - startingOffset); deleteExpression.setIsGlobal(global); @@ -901,24 +990,24 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { @Override - protected IASTExpression unaryExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException { + protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { switch (LT(1)) { case IToken.tSTAR: - return unarayExpression(IASTUnaryExpression.op_star, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_star, ctx); case IToken.tAMPER: - return unarayExpression(IASTUnaryExpression.op_amper, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_amper, ctx); case IToken.tPLUS: - return unarayExpression(IASTUnaryExpression.op_plus, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_plus, ctx); case IToken.tMINUS: - return unarayExpression(IASTUnaryExpression.op_minus, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_minus, ctx); case IToken.tNOT: - return unarayExpression(IASTUnaryExpression.op_not, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_not, ctx); case IToken.tBITCOMPLEMENT: - return unarayExpression(IASTUnaryExpression.op_tilde, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_tilde, ctx); case IToken.tINCR: - return unarayExpression(IASTUnaryExpression.op_prefixIncr, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx); case IToken.tDECR: - return unarayExpression(IASTUnaryExpression.op_prefixDecr, inBinaryExpression); + return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx); case IToken.t_new: return newExpression(); case IToken.t_delete: @@ -930,23 +1019,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_delete: return deleteExpression(); default: - return postfixExpression(inBinaryExpression); + return postfixExpression(ctx); } case IToken.t_sizeof: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, inBinaryExpression); + IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx); case IGCCToken.t_typeof: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, inBinaryExpression); + IASTTypeIdExpression.op_typeof, IASTUnaryExpression.op_typeof, ctx); case IGCCToken.t___alignof__: return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, inBinaryExpression); + IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx); default: - return postfixExpression(inBinaryExpression); + return postfixExpression(ctx); } } - private IASTExpression postfixExpression(boolean inBinaryExpression) throws EndOfFileException, BacktrackException { + private IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { IASTExpression firstExpression = null; boolean isTemplate = false; @@ -970,7 +1059,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } catch (BacktrackException bt) { } backup(m); - firstExpression= primaryExpression(); + firstExpression= primaryExpression(ctx); break; case IToken.t_typename: @@ -981,7 +1070,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(); templateTokenConsumed = true; } - IASTName name = idExpression(); + IASTName name = qualifiedName(CastExprCtx.eNotBExpr); // treat as not in binary to force template arguments if (LT(1) != IToken.tLPAREN) { throwBacktrack(LA(1)); } @@ -1036,11 +1125,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_typeid: int so = consume().getOffset(); firstExpression = parseTypeidInParenthesisOrUnaryExpression(true, so, - ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, inBinaryExpression); + ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid, ctx); break; default: - firstExpression = primaryExpression(); + firstExpression = primaryExpression(ctx); break; } IASTExpression secondExpression = null; @@ -1107,7 +1196,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - IASTName name = idExpression(); + IASTName name = qualifiedName(ctx); if (name == null) throwBacktrack(((ASTNode) firstExpression).getOffset(), @@ -1130,7 +1219,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - name = idExpression(); + name = qualifiedName(ctx); if (name == null) throwBacktrack(((ASTNode) firstExpression).getOffset(), @@ -1185,7 +1274,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { @Override - protected IASTExpression primaryExpression() throws EndOfFileException, BacktrackException { + protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException { IToken t = null; IASTLiteralExpression literalExpression = null; switch (LT(1)) { @@ -1238,7 +1327,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } t = consume(); int finalOffset= 0; - IASTExpression lhs= expression(true, true, false); // instead of expression(), to keep the stack smaller + IASTExpression lhs= expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID); // instead of expression(), to keep the stack smaller switch (LT(1)) { case IToken.tRPAREN: case IToken.tEOC: @@ -1253,7 +1342,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_operator: case IToken.tCOMPLETION: case IToken.tBITCOMPLEMENT: { - IASTName name = idExpression(); + IASTName name = qualifiedName(ctx); IASTIdExpression idExpression = nodeFactory.newIdExpression(name); ((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset() + ((ASTNode) name).getLength() - ((ASTNode) name).getOffset()); @@ -1320,7 +1409,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.tIDENTIFIER: case IToken.tCOLONCOLON: case IToken.tCOMPLETION: - name = qualifiedName(); + name = qualifiedName(CastExprCtx.eNotBExpr); break; default: throwBacktrack(offset, endOffset - offset); @@ -1351,7 +1440,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(); } - IASTName name = idExpression(); + IASTName name = qualifiedName(CastExprCtx.eNotBExpr); int end; switch (LT(1)) { case IToken.tSEMI: @@ -1469,7 +1558,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } List parms= templateParameterList(); - consume(IToken.tGT); + consume(IToken.tGT, IToken.tGT_in_SHIFTR); IASTDeclaration d = declaration(option); ICPPASTTemplateDeclaration templateDecl = nodeFactory.newTemplateDeclaration(d); ((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset()); @@ -1503,7 +1592,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { for (;;) { final int lt1= LT(1); - if (lt1 == IToken.tGT || lt1 == IToken.tEOC) + if (lt1 == IToken.tGT || lt1 == IToken.tEOC || lt1 == IToken.tGT_in_SHIFTR) return returnValue; if (lt1 == IToken.t_class || lt1 == IToken.t_typename) { IToken startingToken = LA(1); @@ -1537,7 +1626,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(IToken.tLT); List subResult = templateParameterList(); - consume(IToken.tGT); + consume(IToken.tGT, IToken.tGT_in_SHIFTR); int last = consume(IToken.t_class).getEndOffset(); IASTName identifierName = null; IASTExpression optionalExpression = null; @@ -1547,7 +1636,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { last = calculateEndOffset(identifierName); if (LT(1) == IToken.tASSIGN) { // optional = type-id consume(); - optionalExpression = primaryExpression(); + optionalExpression = primaryExpression(CastExprCtx.eNotBExpr); last = calculateEndOffset(optionalExpression); } } else @@ -1690,7 +1779,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; } - IASTName qualifiedName= qualifiedName(); + IASTName qualifiedName= qualifiedName(CastExprCtx.eNotBExpr); endOffset = consume(IToken.tSEMI).getEndOffset(); ICPPASTNamespaceAlias alias = nodeFactory.newNamespaceAlias(name, qualifiedName); @@ -1892,7 +1981,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { consume(); ctorLoop: for (;;) { int offset= LA(1).getOffset(); - IASTName name = qualifiedName(); + IASTName name = qualifiedName(CastExprCtx.eNotBExpr); int endOffset; IASTExpression expressionList = null; @@ -2161,7 +2250,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (encounteredTypename || encounteredRawType) break declSpecifiers; consume(); - identifier= qualifiedName(); + identifier= qualifiedName(CastExprCtx.eNotBExpr); endOffset= calculateEndOffset(identifier); isTypename = true; encounteredTypename= true; @@ -2180,7 +2269,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } } - identifier= qualifiedName(); + identifier= qualifiedName(CastExprCtx.eNotBExpr); if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC) throwBacktrack(LA(1)); @@ -2235,7 +2324,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { throwBacktrack(LA(1)); typeofExpression= parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(), - IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, false); + IGNUASTTypeIdExpression.op_typeof, IGNUASTUnaryExpression.op_typeof, CastExprCtx.eNotBExpr); encounteredTypename= true; endOffset= calculateEndOffset(typeofExpression); @@ -2374,7 +2463,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // if __attribute__ or __declspec occurs after struct/union/class and before the identifier __attribute_decl_seq(supportAttributeSpecifiers, supportDeclspecSpecifiers); - IASTName name = qualifiedName(); + IASTName name = qualifiedName(CastExprCtx.eNotBExpr); ICPPASTElaboratedTypeSpecifier elaboratedTypeSpec = nodeFactory.newElaboratedTypeSpecifier(eck, name); ((ASTNode) elaboratedTypeSpec).setOffsetAndLength(t.getOffset(), calculateEndOffset(name) - t.getOffset()); @@ -2628,51 +2717,50 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } - protected IASTInitializer initializerClause(boolean inAggregateInitializer) throws EndOfFileException, BacktrackException { - if (LT(1) == IToken.tLBRACE) { - int startingOffset = consume().getOffset(); + protected IASTInitializer initializerClause(boolean inAggregateInitializer) throws EndOfFileException, + BacktrackException { + if (LT(1) == IToken.tLBRACE) { + int startingOffset = consume().getOffset(); - IASTInitializerList result = nodeFactory.newInitializerList(); - ((ASTNode) result).setOffset(startingOffset); + IASTInitializerList result = nodeFactory.newInitializerList(); + ((ASTNode) result).setOffset(startingOffset); - if (LT(1) == (IToken.tRBRACE)) { - int l = consume().getEndOffset(); - ((ASTNode) result).setLength(l - startingOffset); - return result; - } + if (LT(1) == (IToken.tRBRACE)) { + int endOffset = consume().getEndOffset(); + setRange(result, startingOffset, endOffset); + return result; + } - // otherwise it is a list of initializer clauses + // otherwise it is a list of initializer clauses + for (;;) { + if (LT(1) == IToken.tRBRACE) + break; - for (;;) { - if (LT(1) == IToken.tRBRACE) - break; + // clause may be null, add to initializer anyways, such that the + // actual size can be computed. + IASTInitializer clause = initializerClause(true); + result.addInitializer(clause); + if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC) + break; + consume(IToken.tCOMMA); + } + int endOffset = consume().getEndOffset(); // tRBRACE + setRange(result, startingOffset, endOffset); + return result; + } - // clause may be null, add to initializer anyways, such that the - // actual size can be computed. - IASTInitializer clause = initializerClause(true); - result.addInitializer(clause); - if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC) - break; - consume(IToken.tCOMMA); - } - int l = consume().getEndOffset(); // tRBRACE - ((ASTNode) result).setLength(l - startingOffset); - return result; - } + // no brace, so try an assignment expression + final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID; + IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx); + if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) { + if (!ASTQueries.canContainName(assignmentExpression)) + return null; + } - // if we get this far, it means that we did not - // try this now instead - // assignmentExpression - IASTExpression assignmentExpression = expression(false, true, fInTemplateParameterList); - if (inAggregateInitializer && skipTrivialExpressionsInAggregateInitializers) { - if (!ASTQueries.canContainName(assignmentExpression)) - return null; - } - - IASTInitializerExpression result = nodeFactory.newInitializerExpression(assignmentExpression); - ((ASTNode) result).setOffsetAndLength(((ASTNode) assignmentExpression)); - return result; - } + IASTInitializerExpression result = nodeFactory.newInitializerExpression(assignmentExpression); + setRange(result, assignmentExpression); + return result; + } @Override @@ -2684,7 +2772,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTDeclSpecifier declSpecifier = null; IASTDeclarator declarator = null; - rejectLogicalOperatorInTemplateID++; try { Decl decl= declSpecifierSequence_initDeclarator(option, false); declSpecifier= decl.fDeclSpec1; @@ -2694,9 +2781,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return null; } catch (BacktrackException bt) { return null; - } finally { - rejectLogicalOperatorInTemplateID--; - } + } IASTTypeId result = nodeFactory.newTypeId(declSpecifier, declarator); setRange(result, offset, figureEndOffset(declSpecifier, declarator)); return result; @@ -2744,7 +2829,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (option.fRequireAbstract) throwBacktrack(LA(1)); - final IASTName declaratorName= qualifiedName(); + final IASTName declaratorName= qualifiedName(CastExprCtx.eNotBExpr); endOffset= calculateEndOffset(declaratorName); return declarator(pointerOps, declaratorName, null, startingOffset, endOffset, strategy, option); } @@ -2860,7 +2945,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } if (coloncolon != 0) { try { - name= qualifiedName(); + name= qualifiedName(CastExprCtx.eNotBExpr); if (name.getLookupKey().length != 0) { backup(mark); return; @@ -3167,7 +3252,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // class name IASTName name = null; if (LT(1) == IToken.tIDENTIFIER) - name = qualifiedName(); + name = qualifiedName(CastExprCtx.eNotBExpr); else name = nodeFactory.newName(); @@ -3253,7 +3338,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.tIDENTIFIER: case IToken.tCOMPLETION: // to get templates right we need to use the class as the scope - name = qualifiedName(); + name = qualifiedName(CastExprCtx.eNotBExpr); endOffset= calculateEndOffset(name); break; case IToken.tCOMMA: diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java index 68b2ca5e2d7..ee447ccac54 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java @@ -171,6 +171,7 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { private int fContentAssistLimit= -1; private boolean fHandledCompletion= false; + private boolean fSplitShiftRightOperator= false; // state information private final CharArrayMap fMacroDictionary = new CharArrayMap(512); @@ -238,6 +239,9 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } } + public void setSplitShiftROperator(boolean val) { + fSplitShiftRightOperator= val; + } public void setComputeImageLocations(boolean val) { fLexOptions.fCreateImageLocations= val; @@ -442,7 +446,8 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { } /** - * Returns the next token from the preprocessor without concatenating string literals. + * Returns the next token from the preprocessor without concatenating string literals + * and also without splitting the shift-right operator. */ private Token fetchToken() throws OffsetLimitReachedException { if (fIsFirstFetchToken) { @@ -537,7 +542,6 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { case IToken.tLSTRING: case IToken.tUTF16STRING: case IToken.tUTF32STRING: - StringType st = StringType.fromToken(tt1); Token t2; StringBuffer buf= null; @@ -580,6 +584,18 @@ public class CPreprocessor implements ILexerLog, IScanner, IAdaptable { image[image.length - 1]= '"'; t1= new TokenWithImage(st.getTokenValue(), null, t1.getOffset(), endOffset, image); } + break; + + case IToken.tSHIFTR: + if (fSplitShiftRightOperator) { + int offset= t1.getOffset(); + endOffset= t1.getEndOffset(); + + t1.setType(IToken.tGT_in_SHIFTR); + t1.setOffset(offset, offset+1); + t2= new Token(IToken.tGT_in_SHIFTR, t1.fSource, offset+1, endOffset); + pushbackToken(t2); + } } if (fLastToken != null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java index ea5776c30bf..25619c4e575 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/TokenUtil.java @@ -112,6 +112,7 @@ public class TokenUtil { case IToken.tSHIFTRASSIGN: return Keywords.cpSHIFTRASSIGN; case IToken.tSHIFTR: return Keywords.cpSHIFTR; case IToken.tGTEQUAL: return Keywords.cpGTEQUAL; + case IToken.tGT_in_SHIFTR: case IToken.tGT: return Keywords.cpGT; case IToken.tSHIFTLASSIGN: return Keywords.cpSHIFTLASSIGN; case IToken.tELLIPSIS: return Keywords.cpELLIPSIS;