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 a6cff09c463..98223b1759e 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 @@ -10537,4 +10537,18 @@ public class AST2TemplateTests extends AST2CPPTestBase { IType waldo = helper.assertNonProblem("Waldo"); assertSameType(CommonCPPTypes.void_, waldo); } + + // template int constant8f(); + // + // template + // void foo() { + // constant8f< + // i0 < 0, i0 < 0, + // i1 < 0, i1 < 0, + // i2 < 0, i2 < 0, + // i3 < 0, i3 < 0>(); + // } + public void testTemplateIdAmbiguity_529696() throws Exception { + parseAndCheckBindings(); + } } 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 3ff0f8204f9..1a9ed31648a 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 @@ -1631,19 +1631,32 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { protected abstract IASTDeclaration declaration(DeclarationOptions option) throws BacktrackException, EndOfFileException; + protected Decl declSpecifierSeq(DeclarationOptions option) throws BacktrackException, EndOfFileException { + return declSpecifierSeq(option, null); + } + /** * Parses for two alternatives of a declspec sequence. If there is a second alternative the token after the second alternative * is returned, such that the parser can continue after both variants. */ - protected abstract Decl declSpecifierSeq(DeclarationOptions option) throws BacktrackException, EndOfFileException; + protected abstract Decl declSpecifierSeq(DeclarationOptions option, ITemplateIdStrategy strat) + throws BacktrackException, EndOfFileException; + protected Decl declSpecifierSequence_initDeclarator(final DeclarationOptions option, + boolean acceptCompoundWithoutDtor) + throws EndOfFileException, FoundAggregateInitializer, BacktrackException { + return declSpecifierSequence_initDeclarator(option, acceptCompoundWithoutDtor, null); + } + /** * Parses for two alternatives of a declspec sequence followed by a initDeclarator. * A second alternative is accepted only, if it ends at the same point of the first alternative. Otherwise the * longer alternative is selected. */ - protected Decl declSpecifierSequence_initDeclarator(final DeclarationOptions option, boolean acceptCompoundWithoutDtor) throws EndOfFileException, FoundAggregateInitializer, BacktrackException { - Decl result= declSpecifierSeq(option); + protected Decl declSpecifierSequence_initDeclarator(final DeclarationOptions option, + boolean acceptCompoundWithoutDtor, ITemplateIdStrategy strat) + throws EndOfFileException, FoundAggregateInitializer, BacktrackException { + Decl result= declSpecifierSeq(option, strat); final int lt1 = LTcatchEOF(1); if (lt1 == IToken.tEOC) 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 b88e8c630e8..2622b978491 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 @@ -911,7 +911,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser { SHORT=0x10, UNSIGNED= 0x20, SIGNED=0x40, COMPLEX=0x80, IMAGINARY=0x100; @Override - protected Decl declSpecifierSeq(final DeclarationOptions declOption) throws BacktrackException, EndOfFileException { + protected Decl declSpecifierSeq(final DeclarationOptions declOption, ITemplateIdStrategy strat) + throws BacktrackException, EndOfFileException { int storageClass= IASTDeclSpecifier.sc_unspecified; int simpleType= IASTSimpleDeclSpecifier.t_unspecified; int options= 0; 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 b0ce8e6b18c..f35d19f3b5c 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 @@ -751,10 +751,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { private IASTNode templateArgument(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { IToken argStart = mark(); + int markBranchPoint = ((TemplateIdStrategy) strat).getCurrentBranchPoint(); ICPPASTTypeId typeId= null; int lt1= 0; try { - typeId= typeId(DeclarationOptions.TYPEID); + typeId= typeId(DeclarationOptions.TYPEID, strat); lt1 = LT(1); } catch (BacktrackException e) { if (e.isFatal()) { @@ -849,6 +850,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // Not a type-id, parse as expression. backup(argStart); + ((TemplateIdStrategy) strat).backupToBranchPoint(markBranchPoint); IASTExpression expr= expression(ExprKind.eAssignment, BinaryExprCtx.eInTemplateID, null, strat); if (LT(1) == IToken.tELLIPSIS) { expr= addPackExpansion(expr, consume()); @@ -3050,21 +3052,23 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { * {"enum"} enumSpecifier */ @Override - protected Decl declSpecifierSeq(final DeclarationOptions option) throws BacktrackException, EndOfFileException { - return declSpecifierSeq(option, false); + protected Decl declSpecifierSeq(final DeclarationOptions option, ITemplateIdStrategy strat) + throws BacktrackException, EndOfFileException { + return declSpecifierSeq(option, false, strat); } private ICPPASTDeclSpecifier simpleTypeSpecifier() throws BacktrackException, EndOfFileException { - Decl d= declSpecifierSeq(null, true); + Decl d= declSpecifierSeq(null, true, null); return (ICPPASTDeclSpecifier) d.fDeclSpec1; } private ICPPASTDeclSpecifier simpleTypeSpecifierSequence() throws BacktrackException, EndOfFileException { - Decl d= declSpecifierSeq(null, false); + Decl d= declSpecifierSeq(null, false, null); return (ICPPASTDeclSpecifier) d.fDeclSpec1; } - private Decl declSpecifierSeq(final DeclarationOptions option, final boolean single) throws BacktrackException, EndOfFileException { + private Decl declSpecifierSeq(final DeclarationOptions option, final boolean single, + ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException { int storageClass = IASTDeclSpecifier.sc_unspecified; int simpleType = IASTSimpleDeclSpecifier.t_unspecified; int options= 0; @@ -3324,7 +3328,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } } - identifier= qualifiedName(); + identifier= qualifiedName(CastExprCtx.eNotInBExpr, strat); if (identifier.getLookupKey().length == 0 && LT(1) != IToken.tEOC) throwBacktrack(LA(1)); @@ -4161,6 +4165,11 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { @Override protected ICPPASTTypeId typeId(DeclarationOptions option) throws EndOfFileException, BacktrackException { + return typeId(option, null); + } + + protected ICPPASTTypeId typeId(DeclarationOptions option, ITemplateIdStrategy strat) + throws EndOfFileException, BacktrackException { if (!canBeTypeSpecifier()) { throwBacktrack(LA(1)); } @@ -4169,7 +4178,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { IASTDeclarator declarator = null; try { - Decl decl= declSpecifierSequence_initDeclarator(option, false); + Decl decl= declSpecifierSequence_initDeclarator(option, false, strat); declSpecifier= decl.fDeclSpec1; declarator= decl.fDtor1; } catch (FoundAggregateInitializer lie) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/TemplateIdStrategy.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/TemplateIdStrategy.java index 0eec024fe6f..7e0a92a890e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/TemplateIdStrategy.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/TemplateIdStrategy.java @@ -27,7 +27,7 @@ import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.ITem * When parsing, we potentially need to consider both possibilities for each use of '<'. * * An instance of this class is used to track alternative parses in a segment of code that includes one or - * more uses of '<' preceded by names. An alternative consists of a choices (template-id or not) for each + * more uses of '<' preceded by names. An alternative consists of a choice (template-id or not) for each * name. At a given point in time, the instance has a notion of a current alternative, and a current * position within that alternative. * @@ -145,4 +145,20 @@ final class TemplateIdStrategy implements ITemplateIdStrategy { public IASTName[] getTemplateNames() { return ArrayUtil.trim(fTemplateNames); } + + /** + * Sometimes, a BacktrackException can be thrown and handled during the processing + * of a single alternative (that is, the exception does not bubble up all the way + * to the point where setNextAlternative() would be called). In such a case, when + * backtracking we need to restore the branch point that was active at the point + * we're backing up to (otherwise, the current branch point could get out of sync + * with the parsing position). These methods facilitate marking and backing up to + * the current branch point for such situations. + */ + public int getCurrentBranchPoint() { + return fCurrentBranchPoint; + } + public void backupToBranchPoint(int branchPoint) { + fCurrentBranchPoint = branchPoint; + } } \ No newline at end of file