1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-03 23:25:26 +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();
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 interface ITemplateIdStrategy {
boolean shallParseAsTemplateID(IASTName name);
}
protected static class FoundAggregateInitializer extends Exception {

View file

@ -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);
@ -227,8 +231,10 @@ 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<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 endOffset = 0;
List<IASTNode> 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());

View file

@ -27,25 +27,19 @@ 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) {
boolean templateID= fSimpleIDs == null || !fSimpleIDs.get(fCurrentBranchPoint);
if (templateID) {
fTemplateNames= ArrayUtil.append(fTemplateNames, name);
}
return templateID;
}
public boolean setNextAlternative() {
final int bp = fCurrentBranchPoint;