1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-04 07:35:24 +02:00

Bug 364225: NPE in template ambiguity handling in delete expression.

This commit is contained in:
Markus Schorn 2011-11-29 13:15:55 +01:00
parent c253ee2f96
commit bc6ff322dc
4 changed files with 56 additions and 42 deletions

View file

@ -5494,4 +5494,26 @@ public class AST2TemplateTests extends AST2BaseTest {
final String code= getAboveComment(); final String code= getAboveComment();
parseAndCheckBindings(code); parseAndCheckBindings(code);
} }
// template<class T> struct A {
// bool b;
// };
// class B {
// };
// template<class T> T * func();
// void test1() {
// delete func<A<B>>(); // This line causes the NPE
// }
//
// template<bool> struct C {
// int* ptr;
// };
// void test2() {
// int a = 0, b = 1;
// delete C< a<b >::ptr;
// delete C< A<B>::b >::ptr;
// }
public void testTemplateAmbiguityInDeleteExpression_364225() throws Exception {
parseAndCheckBindings();
}
} }

View file

@ -90,6 +90,7 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
*/ */
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
public interface ITemplateIdStrategy { public interface ITemplateIdStrategy {
boolean shallParseAsTemplateID(IASTName name);
} }
protected static class FoundAggregateInitializer extends Exception { protected static class FoundAggregateInitializer extends Exception {

View file

@ -209,11 +209,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
private IASTName qualifiedName() throws BacktrackException, EndOfFileException { private IASTName qualifiedName() throws BacktrackException, EndOfFileException {
return ambiguousQualifiedName(CastExprCtx.eNotInBExpr);
}
private IASTName ambiguousQualifiedName(CastExprCtx ctx) throws BacktrackException, EndOfFileException {
TemplateIdStrategy strat= new TemplateIdStrategy(); TemplateIdStrategy strat= new TemplateIdStrategy();
IToken m= mark(); IToken m= mark();
for(;;) { for(;;) {
try { try {
return qualifiedName(strat, CastExprCtx.eNotInBExpr); return qualifiedName(ctx, strat);
} catch (BacktrackException e) { } catch (BacktrackException e) {
if (strat.setNextAlternative()) { if (strat.setNextAlternative()) {
backup(m); backup(m);
@ -227,8 +231,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
/** /**
* Parses a qualified name. * Parses a qualified name.
*/ */
private IASTName qualifiedName(ITemplateIdStrategy s, CastExprCtx ctx) throws BacktrackException, EndOfFileException { private IASTName qualifiedName(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException {
final TemplateIdStrategy strat= (TemplateIdStrategy) s; if (strat == null)
return ambiguousQualifiedName(ctx);
ICPPASTQualifiedName qname= null; ICPPASTQualifiedName qname= null;
IASTName name= null; IASTName name= null;
final int offset= LA(1).getOffset(); final int offset= LA(1).getOffset();
@ -288,11 +294,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (haveArgs == -1) { if (haveArgs == -1) {
templateID= false; templateID= false;
} else if (haveArgs == 0) { } else if (haveArgs == 0) {
if (strat.ignoreTemplateID()) { templateID= strat.shallParseAsTemplateID(name);
templateID= false;
} else {
strat.addTemplateName(name);
}
} }
} }
if (templateID) { if (templateID) {
@ -350,7 +352,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return name; 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 // Parse for template arguments
consume(IToken.tLT); consume(IToken.tLT);
List<IASTNode> list = templateArgumentList(strat); List<IASTNode> list = templateArgumentList(strat);
@ -566,7 +568,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
} }
private List<IASTNode> templateArgumentList(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { private List<IASTNode> templateArgumentList(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
int startingOffset = LA(1).getOffset(); int startingOffset = LA(1).getOffset();
int endOffset = 0; int endOffset = 0;
List<IASTNode> list= null; List<IASTNode> list= null;
@ -596,7 +598,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return list; return list;
} }
private IASTNode templateArgument(TemplateIdStrategy strat) throws EndOfFileException, BacktrackException { private IASTNode templateArgument(ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
IToken argStart = mark(); IToken argStart = mark();
ICPPASTTypeId typeId= null; ICPPASTTypeId typeId= null;
int lt1= 0; int lt1= 0;
@ -742,7 +744,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return expression(ExprKind.eConstant, BinaryExprCtx.eNotInTemplateID, null, null); 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; final boolean allowComma= kind==ExprKind.eExpression;
boolean allowAssignment= kind !=ExprKind.eConstant; boolean allowAssignment= kind !=ExprKind.eConstant;
@ -750,12 +752,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return throwExpression(); return throwExpression();
} }
final boolean handleVariants= strat == null;
if (handleVariants) {
strat= new TemplateIdStrategy();
}
final int startOffset= expr != null ? ((ASTNode) expr).getOffset() : LA(1).getOffset(); final int startOffset= expr != null ? ((ASTNode) expr).getOffset() : LA(1).getOffset();
int lt1; int lt1;
int conditionCount= 0; int conditionCount= 0;
@ -763,7 +759,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
NameOrTemplateIDVariants variants= null; NameOrTemplateIDVariants variants= null;
if (expr == null) { if (expr == null) {
Object e = castExpressionForBinaryExpression(handleVariants, strat); Object e = castExpressionForBinaryExpression(strat);
if (e instanceof IASTExpression) { if (e instanceof IASTExpression) {
expr= (IASTExpression) e; expr= (IASTExpression) e;
} else { } else {
@ -934,7 +930,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// Cast expression // Cast expression
IToken m= mark(); IToken m= mark();
try { try {
Object e = castExpressionForBinaryExpression(handleVariants, strat); Object e = castExpressionForBinaryExpression(strat);
if (e instanceof IASTExpression) { if (e instanceof IASTExpression) {
expr= (IASTExpression) e; expr= (IASTExpression) e;
} else { } else {
@ -999,18 +995,19 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return buildExpression(lastOperator, expr); return buildExpression(lastOperator, expr);
} }
public Object castExpressionForBinaryExpression(boolean handleVariants, final TemplateIdStrategy strat) public Object castExpressionForBinaryExpression(ITemplateIdStrategy s)
throws EndOfFileException, BacktrackException { throws EndOfFileException, BacktrackException {
if (!handleVariants) if (s != null) {
return castExpression(CastExprCtx.eDirectlyInBExpr, strat); return castExpression(CastExprCtx.eDirectlyInBExpr, s);
}
TemplateIdStrategy strat= new TemplateIdStrategy();
Variant variants= null; Variant variants= null;
IASTExpression singleExpression= null; IASTExpression singleExpression= null;
IASTName[] firstNames= null; IASTName[] firstNames= null;
final IToken mark= mark(); final IToken mark= mark();
IToken lastToken= null; IToken lastToken= null;
strat.reset();
for(;;) { for(;;) {
try { try {
IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat); IASTExpression e = castExpression(CastExprCtx.eDirectlyInBExpr, strat);
@ -1554,7 +1551,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
isTemplate = true; isTemplate = true;
} }
IASTName name = qualifiedName(strat, ctx); IASTName name = qualifiedName(ctx, strat);
if (name == null) if (name == null)
throwBacktrack(((ASTNode) firstExpression).getOffset(), throwBacktrack(((ASTNode) firstExpression).getOffset(),
@ -1577,7 +1574,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
isTemplate = true; isTemplate = true;
} }
name = qualifiedName(strat, ctx); name = qualifiedName(ctx, strat);
if (name == null) if (name == null)
throwBacktrack(((ASTNode) firstExpression).getOffset(), throwBacktrack(((ASTNode) firstExpression).getOffset(),
@ -1690,7 +1687,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IToken.t_operator: case IToken.t_operator:
case IToken.tCOMPLETION: case IToken.tCOMPLETION:
case IToken.tBITCOMPLEMENT: { case IToken.tBITCOMPLEMENT: {
IASTName name = qualifiedName(strat, ctx); IASTName name = qualifiedName(ctx, strat);
IASTIdExpression idExpression = nodeFactory.newIdExpression(name); IASTIdExpression idExpression = nodeFactory.newIdExpression(name);
((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset() ((ASTNode) idExpression).setOffsetAndLength(((ASTNode) name).getOffset(), ((ASTNode) name).getOffset()
+ ((ASTNode) name).getLength() - ((ASTNode) name).getOffset()); + ((ASTNode) name).getLength() - ((ASTNode) name).getOffset());

View file

@ -27,24 +27,18 @@ final class TemplateIdStrategy implements ITemplateIdStrategy {
private IASTName[] fTemplateNames; private IASTName[] fTemplateNames;
public TemplateIdStrategy() { public TemplateIdStrategy() {
reset();
}
public void reset() {
fCurrentBranchPoint= -1; fCurrentBranchPoint= -1;
fTemplateNames= IASTName.EMPTY_NAME_ARRAY; fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
if (fSimpleIDs != null) {
fSimpleIDs.clear();
}
} }
public boolean ignoreTemplateID() { public boolean shallParseAsTemplateID(IASTName name) {
fCurrentBranchPoint++; fCurrentBranchPoint++;
return fSimpleIDs == null ? false : fSimpleIDs.get(fCurrentBranchPoint);
}
public void addTemplateName(IASTName name) { boolean templateID= fSimpleIDs == null || !fSimpleIDs.get(fCurrentBranchPoint);
fTemplateNames= ArrayUtil.append(fTemplateNames, name); if (templateID) {
fTemplateNames= ArrayUtil.append(fTemplateNames, name);
}
return templateID;
} }
public boolean setNextAlternative() { public boolean setNextAlternative() {