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 2e9a6752e5a..a522e97af8b 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 @@ -4994,4 +4994,18 @@ public class AST2TemplateTests extends AST2BaseTest { assertEquals(1, names.length); assertEquals("CT", names[0].toString()); } + + public void testBug316704() throws Exception { + StringBuilder code= new StringBuilder("typedef if_< bool,"); + for (int i = 0; i < 50; i++) { + code.append('\n').append("if_,"); + for (int i = 0; i < 50; i++) { + code.append('\n').append("int_<0> >::type,"); + } + code.append("int_<0> >::type tdef;"); + IASTTranslationUnit tu= parse(code.toString(), ParserLanguage.CPP, true, true); + assertEquals(1, tu.getDeclarations().length); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java index c464d37cac5..29e971a47a3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2009 IBM Corporation and others. + * Copyright (c) 2004, 2010 IBM Corporation 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 @@ -65,6 +65,9 @@ public abstract class ASTAmbiguousNode extends ASTNode { protected void beforeResolution() { } + protected void beforeAlternative(IASTNode alternative) { + } + protected void afterResolution(ASTVisitor resolver, IASTNode best) { } @@ -78,6 +81,8 @@ public abstract class ASTAmbiguousNode extends ASTNode { int minIssues = Integer.MAX_VALUE; for (IASTNode alternative : alternatives) { + beforeAlternative(alternative); + // setup the ast to use the alternative owner.replace(nodeToReplace, alternative); nodeToReplace= alternative; @@ -134,7 +139,7 @@ public abstract class ASTAmbiguousNode extends ASTNode { return bestAlternative; } - public boolean isLValue() { + public boolean isLValue() { return false; } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java index f38dbc9e6a2..9d6d73f36de 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2009 Symbian Software Systems and others. + * Copyright (c) 2008, 2010 Symbian Software Systems 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 @@ -15,8 +15,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import java.util.ArrayList; import java.util.List; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +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.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument; @@ -53,6 +57,33 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements } } + + @Override + protected void beforeAlternative(IASTNode node) { + // The name may be shared between the alternatives make sure it's parent is set correctly + if (node instanceof IASTTypeId) { + IASTDeclSpecifier declSpec = ((IASTTypeId) node).getDeclSpecifier(); + if (declSpec instanceof IASTNamedTypeSpecifier) { + IASTNamedTypeSpecifier namedTypeSpec= (IASTNamedTypeSpecifier) declSpec; + final IASTName name = namedTypeSpec.getName(); + name.setBinding(null); + namedTypeSpec.setName(name); + } + } else if (node instanceof IASTIdExpression) { + IASTIdExpression id= (IASTIdExpression) node; + final IASTName name = id.getName(); + name.setBinding(null); + id.setName(name); + } + } + + + @Override + protected void afterResolution(ASTVisitor resolver, IASTNode best) { + beforeAlternative(best); + } + + public IASTNode copy() { throw new UnsupportedOperationException(); } 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 fe8fa28f9a1..9cca528d573 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 @@ -559,34 +559,37 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // This is potentially a type-id, now check ambiguity with id-expression IASTDeclSpecifier declspec= typeId.getDeclSpecifier(); if (declspec instanceof IASTNamedTypeSpecifier) { - IASTName name= ((IASTNamedTypeSpecifier) declspec).getName(); + final IASTNamedTypeSpecifier namedDeclspec = (IASTNamedTypeSpecifier) declspec; + IASTName name= namedDeclspec.getName(); if (name.contains(typeId)) { // A template-id cannot be used in an id-expression as a template argument // 5.1-11 A template-id shall be used as an unqualified-id only as specified in // 14.7.2, 14.7, and 14.5.4. - name= name.getLastName(); - if (!(name instanceof ICPPASTTemplateId)) { + if (!(name.getLastName() instanceof ICPPASTTemplateId)) { IToken typeIdEnd= mark(); - backup(argStart); + IASTIdExpression idExpr= setRange(nodeFactory.newIdExpression(name), name); try { - IASTExpression expression = expression(ExprKind.eAssignment, exprCtx); - if (expression instanceof IASTIdExpression) { - if (mark() == typeIdEnd) { - if (LT(1) == IToken.tELLIPSIS) { - IToken ellipsis= consume(); - addPackExpansion(typeId, ellipsis); - expression= addPackExpansion(expression, ellipsis); - } - ICPPASTAmbiguousTemplateArgument ambiguity= createAmbiguousTemplateArgument(); - ambiguity.addTypeId(typeId); - ambiguity.addIdExpression(expression); - return ambiguity; + IASTExpression expression = expression(ExprKind.eAssignment, exprCtx, idExpr); + boolean isAmbiguous= (expression == idExpr); + if (LT(1) == IToken.tELLIPSIS) { + IToken ellipsis= consume(); + if (isAmbiguous) { + addPackExpansion(typeId, ellipsis); } + expression= addPackExpansion(expression, ellipsis); } + if (isAmbiguous) { + ICPPASTAmbiguousTemplateArgument ambiguity= createAmbiguousTemplateArgument(); + ambiguity.addTypeId(typeId); + ambiguity.addIdExpression(expression); + return ambiguity; + } + return expression; } catch (BacktrackException e) { // Use the typeId } backup(typeIdEnd); + namedDeclspec.setName(name); } } } @@ -599,7 +602,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // Not a type-id, parse as expression backup(argStart); - IASTExpression expr= expression(ExprKind.eAssignment, exprCtx); + IASTExpression expr= expression(ExprKind.eAssignment, exprCtx, null); if (LT(1) == IToken.tELLIPSIS) { expr= addPackExpansion(expr, consume()); } @@ -683,15 +686,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { @Override protected IASTExpression expression() throws BacktrackException, EndOfFileException { - return expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID); + return expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID, null); } @Override protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException { - return expression(ExprKind.eConstant, BinaryExprCtx.eNoTmplID); + return expression(ExprKind.eConstant, BinaryExprCtx.eNoTmplID, null); } - private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx) throws EndOfFileException, BacktrackException { + private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx, IASTInitializerClause expr) throws EndOfFileException, BacktrackException { final boolean allowComma= kind==ExprKind.eExpression; boolean allowAssignment= kind !=ExprKind.eConstant; final CastExprCtx castCtx= ctx == BinaryExprCtx.eNoTmplID ? CastExprCtx.eBExpr : CastExprCtx.eBExprInTmplID; @@ -703,7 +706,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { int lt1; int conditionCount= 0; BinaryOperator lastOperator= null; - IASTInitializerClause expr= castExpression(castCtx); + if (expr == null) { + expr= castExpression(castCtx); + } loop: while(true) { // Typically after a binary operator there cannot be a throw expression @@ -1376,7 +1381,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } t = consume(); int finalOffset= 0; - IASTExpression lhs= expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID); // instead of expression(), to keep the stack smaller + IASTExpression lhs= expression(ExprKind.eExpression, BinaryExprCtx.eNoTmplID, null); // instead of expression(), to keep the stack smaller switch (LT(1)) { case IToken.tRPAREN: case IToken.tEOC: @@ -2947,7 +2952,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // assignment expression final BinaryExprCtx ctx = fInTemplateParameterList ? BinaryExprCtx.eTmplID : BinaryExprCtx.eNoTmplID; - IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx); + IASTExpression assignmentExpression = expression(ExprKind.eAssignment, ctx, null); if (allowSkipping && skipTrivialExpressionsInAggregateInitializers) { if (!ASTQueries.canContainName(assignmentExpression)) return null;