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 8ff201ed898..c24028ad52d 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 @@ -5494,4 +5494,26 @@ public class AST2TemplateTests extends AST2BaseTest { final String code= getAboveComment(); parseAndCheckBindings(code); } + + // template struct A { + // bool b; + // }; + // class B { + // }; + // template T * func(); + // void test1() { + // delete func>(); // This line causes the NPE + // } + // + // template struct C { + // int* ptr; + // }; + // void test2() { + // int a = 0, b = 1; + // delete C< a::ptr; + // delete C< A::b >::ptr; + // } + public void testTemplateAmbiguityInDeleteExpression_364225() 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 8baba365940..5d4ed6985a7 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 @@ -90,6 +90,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver; */ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { public interface ITemplateIdStrategy { + boolean shallParseAsTemplateID(IASTName name); } protected static class FoundAggregateInitializer extends Exception { 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 46bbf254f39..29378646de9 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 @@ -209,11 +209,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } private IASTName qualifiedName() throws BacktrackException, EndOfFileException { + return ambiguousQualifiedName(CastExprCtx.eNotInBExpr); + } + + private IASTName ambiguousQualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException { TemplateIdStrategy strat= new TemplateIdStrategy(); IToken m= mark(); for(;;) { try { - return qualifiedName(strat, CastExprCtx.eNotInBExpr); + return qualifiedName(ctx, strat); } catch (BacktrackException e) { if (strat.setNextAlternative()) { backup(m); @@ -223,12 +227,14 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } } } - + /** * Parses a qualified name. */ - private IASTName qualifiedName(ITemplateIdStrategy s, CastExprCtx ctx) throws BacktrackException, EndOfFileException { - final TemplateIdStrategy strat= (TemplateIdStrategy) s; + private IASTName qualifiedName(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException { + if (strat == null) + return ambiguousQualifiedName(ctx); + ICPPASTQualifiedName qname= null; IASTName name= null; final int offset= LA(1).getOffset(); @@ -288,11 +294,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { if (haveArgs == -1) { templateID= false; } else if (haveArgs == 0) { - if (strat.ignoreTemplateID()) { - templateID= false; - } else { - strat.addTemplateName(name); - } + templateID= strat.shallParseAsTemplateID(name); } } if (templateID) { @@ -350,7 +352,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return name; } - private IASTName addTemplateArguments(IASTName templateName, TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { + private IASTName addTemplateArguments(IASTName templateName, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { // Parse for template arguments consume(IToken.tLT); List list = templateArgumentList(strat); @@ -566,7 +568,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } } - private List templateArgumentList(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { + private List templateArgumentList(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { int startingOffset = LA(1).getOffset(); int endOffset = 0; List list= null; @@ -596,7 +598,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return list; } - private IASTNode templateArgument(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { + private IASTNode templateArgument(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { IToken argStart = mark(); ICPPASTTypeId typeId= null; int lt1= 0; @@ -742,7 +744,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return expression(ExprKind.eConstant, BinaryExprCtx.eNotInTemplateID, null, null); } - private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx, IASTInitializerClause expr, TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { + private IASTExpression expression(final ExprKind kind, final BinaryExprCtx ctx, IASTInitializerClause expr, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException { final boolean allowComma= kind==ExprKind.eExpression; boolean allowAssignment= kind !=ExprKind.eConstant; @@ -750,12 +752,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return throwExpression(); } - final boolean handleVariants= strat == null; - if (handleVariants) { - strat= new TemplateIdStrategy(); - } - - final int startOffset= expr != null ? ((ASTNode) expr).getOffset() : LA(1).getOffset(); int lt1; int conditionCount= 0; @@ -763,7 +759,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { NameOrTemplateIDVariants variants= null; if (expr == null) { - Object e = castExpressionForBinaryExpression(handleVariants, strat); + Object e = castExpressionForBinaryExpression(strat); if (e instanceof IASTExpression) { expr= (IASTExpression) e; } else { @@ -934,7 +930,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { // Cast expression IToken m= mark(); try { - Object e = castExpressionForBinaryExpression(handleVariants, strat); + Object e = castExpressionForBinaryExpression(strat); if (e instanceof IASTExpression) { expr= (IASTExpression) e; } else { @@ -999,18 +995,19 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { return buildExpression(lastOperator, expr); } - public Object castExpressionForBinaryExpression(boolean handleVariants, final TemplateIdStrategy strat) + public Object castExpressionForBinaryExpression(ITemplateIdStrategy s) throws EndOfFileException, BacktrackException { - if (!handleVariants) - return castExpression(CastExprCtx.eDirectlyInBExpr, strat); + if (s != null) { + return castExpression(CastExprCtx.eDirectlyInBExpr, s); + } + TemplateIdStrategy strat= new TemplateIdStrategy(); Variant variants= null; IASTExpression singleExpression= null; IASTName[] firstNames= null; final IToken mark= mark(); IToken lastToken= null; - strat.reset(); for(;;) { try { IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat); @@ -1554,7 +1551,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - IASTName name = qualifiedName(strat, ctx); + IASTName name = qualifiedName(ctx, strat); if (name == null) throwBacktrack(((ASTNode) firstExpression).getOffset(), @@ -1577,7 +1574,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { isTemplate = true; } - name = qualifiedName(strat, ctx); + name = qualifiedName(ctx, strat); if (name == null) throwBacktrack(((ASTNode) firstExpression).getOffset(), @@ -1690,7 +1687,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { case IToken.t_operator: case IToken.tCOMPLETION: case IToken.tBITCOMPLEMENT: { - IASTName name = qualifiedName(strat, ctx); + IASTName name = qualifiedName(ctx, strat); IASTIdExpression idExpression = nodeFactory.newIdExpression(name); ((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset() + ((ASTNode) name).getLength() - ((ASTNode) name).getOffset()); 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 11243a01cad..f6f3f6b1cac 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,24 +27,18 @@ final class TemplateIdStrategy implements ITemplateIdStrategy { private IASTName[] fTemplateNames; public TemplateIdStrategy() { - reset(); - } - - public void reset() { fCurrentBranchPoint= -1; fTemplateNames= IASTName.EMPTY_NAME_ARRAY; - if (fSimpleIDs != null) { - fSimpleIDs.clear(); - } } - public boolean ignoreTemplateID() { + public boolean shallParseAsTemplateID(IASTName name) { fCurrentBranchPoint++; - return fSimpleIDs == null ? false : fSimpleIDs.get(fCurrentBranchPoint); - } - - public void addTemplateName(IASTName name) { - fTemplateNames= ArrayUtil.append(fTemplateNames, name); + + boolean templateID= fSimpleIDs == null || !fSimpleIDs.get(fCurrentBranchPoint); + if (templateID) { + fTemplateNames= ArrayUtil.append(fTemplateNames, name); + } + return templateID; } public boolean setNextAlternative() { @@ -78,4 +72,4 @@ final class TemplateIdStrategy implements ITemplateIdStrategy { public IASTName[] getTemplateNames() { return ArrayUtil.trim(fTemplateNames); } -} \ No newline at end of file +}