Skip to content

Commit

Permalink
Bug 341747: Ambiguity between template-id and binary expression.
Browse files Browse the repository at this point in the history
  • Loading branch information
Markus Schorn committed Apr 11, 2011
1 parent ee05568 commit 9a2e978
Show file tree
Hide file tree
Showing 12 changed files with 1,155 additions and 335 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
Expand Down Expand Up @@ -5314,4 +5315,74 @@ public void testFunctionWithVoidParamInTypeDeduction() throws Exception {
public void testPartialSpecAfterExplicitInst_339475() throws Exception {
parseAndCheckBindings();
}


// template<bool> struct S {
// static int m();
// };
// template<int> void g(int);
// int f();
// int s;
//
// void test() {
// f < 0 > (1); // Function pointer
// g<0>(1); // Function call
// S<1 && 2>::m(); // m is member of S
// s<1 && 2>::f(); // f is global
// }
public void testTemplateIDAmbiguity_341747a() throws Exception {
IASTTranslationUnit tu= parseAndCheckBindings();
IASTFunctionDefinition fdef= getDeclaration(tu, 4);

IASTExpressionStatement stmt;
stmt= getStatement(fdef, 0);
assertTrue(stmt.getExpression() instanceof IASTBinaryExpression);

stmt= getStatement(fdef, 1);
assertTrue(stmt.getExpression() instanceof IASTFunctionCallExpression);

stmt= getStatement(fdef, 2);
assertTrue(stmt.getExpression() instanceof IASTFunctionCallExpression);

stmt= getStatement(fdef, 0);
assertTrue(stmt.getExpression() instanceof IASTBinaryExpression);
}

// const int a=0, b=1;
// template<int> struct A{};
//
// template<bool B= a<b> struct S {};
// struct X : S<a<b> {};
//
// template<typename B= A<b>> struct T {};
// struct Y : T<A<b>> {};
public void testTemplateIDAmbiguity_341747b() throws Exception {
parseAndCheckBindings();
}

// int a=0, b=1;
// bool bl= false;
// template<bool B> struct S {
// int a;
// };
// void test() {
// S< a<b >::a;
// a < S<bl>::a;
// }
public void testTemplateIDAmbiguity_341747c() throws Exception {
parseAndCheckBindings();
}

// struct S {
// int B;
// };
// template<typename T> struct B {};
// int c;
// void test() {
// S* a=0;
// a->B<c && c>::c;
// }
public void testTemplateIDAmbiguity_341747d() throws Exception {
parseAndCheckBindings();
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2004, 2010 IBM Corporation and others.
* Copyright (c) 2004, 2011 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
Expand Down Expand Up @@ -7102,12 +7102,12 @@ public void testFunctionDeclViaTypedef_86495() throws Exception {
// void f() {
// int a=
public void testLargeExpression_294029() throws Exception {
// when running the test in a suite, it cannot handle more than 200 parenthesis.
// run as a single test it does > 600.
// when running the test in a suite, it cannot handle more than 160 parenthesis.
// run as a single test it does > 500.
sValidateCopy= false;
StringBuilder buf= new StringBuilder();
buf.append(getAboveComment());
final int depth= 200;
final int depth= 160;
for (int i = 0; i < depth; i++) {
buf.append('(');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@
* Base class for the c- and c++ parser.
*/
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
public interface ITemplateIdStrategy {
}

protected static class FoundAggregateInitializer extends Exception {
public final IASTDeclarator fDeclarator;
public final IASTDeclSpecifier fDeclSpec;
Expand Down Expand Up @@ -154,7 +157,7 @@ public int visit(ASTAmbiguousNode node) {
* Information about the context in which a cast-expression is parsed:
* in a binary expression, in a binary expression in a template-id, or elsewhere.
*/
protected static enum CastExprCtx {eBExpr, eBExprInTmplID, eNotBExpr}
protected static enum CastExprCtx {eDirectlyInBExpr, eInBExpr, eNotInBExpr}
protected static enum ExprKind {eExpression, eAssignment, eConstant}

protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
Expand Down Expand Up @@ -921,7 +924,7 @@ else if (mode == ParserMode.COMPLETION_PARSE || mode == ParserMode.SELECTION_PAR
* Models a cast expression followed by an operator. Can be linked into a chain.
* This is done right to left, such that a tree of variants can be built.
*/
protected static class BinaryOperator {
public static class BinaryOperator {
final int fOperatorToken;
final int fLeftPrecedence;
final int fRightPrecedence;
Expand Down Expand Up @@ -949,9 +952,21 @@ public IASTInitializerClause exchange(IASTInitializerClause expr) {
fExpression= expr;
return e;
}

public IASTInitializerClause getExpression() {
return fExpression;
}

public BinaryOperator getNext() {
return fNext;
}

public void setNext(BinaryOperator next) {
fNext = next;
}
}

protected final IASTExpression buildExpression(BinaryOperator leftChain, IASTInitializerClause expr) throws BacktrackException {
public final IASTExpression buildExpression(BinaryOperator leftChain, IASTInitializerClause expr) {
BinaryOperator rightChain= null;
for (;;) {
if (leftChain == null) {
Expand All @@ -973,18 +988,13 @@ protected final IASTExpression buildExpression(BinaryOperator leftChain, IASTIni
}
}

private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) throws BacktrackException {
private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) {
int op, unaryOp= 0;
final IASTInitializerClause right= operator.fExpression;
switch(operator.fOperatorToken) {
case IToken.tQUESTION:
final IASTInitializerClause negative;
if (operator.fNext == null || operator.fNext.fOperatorToken != IToken.tCOLON) {
if (LTcatchEOF(1) != IToken.tEOC || operator.fNext != null) {
assert false;
ASTNode node= (ASTNode) left;
throwBacktrack(node.getOffset(), node.getLength());
}
negative= null;
} else {
negative= operator.fNext.fExpression;
Expand Down Expand Up @@ -1116,25 +1126,26 @@ private IASTExpression buildExpression(IASTExpression left, BinaryOperator opera

default:
assert false;
ASTNode node= (ASTNode) left;
throwBacktrack(node.getOffset(), node.getLength());
return null;
}

IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right));
final CastAmbiguityMarker am = operator.fAmbiguityMarker;
if (am != null) {
assert unaryOp != 0;
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
if (unaryOp != 0) {
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
} else {
assert false;
}
}
return result;
}

protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
protected abstract IASTExpression unaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
protected abstract IASTExpression primaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
protected abstract IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException;
protected abstract IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException;
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException, BacktrackException;

private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
Expand Down Expand Up @@ -1186,7 +1197,7 @@ public ValueCategory getValueCategory() {
}
}

protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
protected final IASTExpression castExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLPAREN) {
final IToken mark= mark();
final int startingOffset= mark.getOffset();
Expand All @@ -1199,7 +1210,7 @@ protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileE
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
boolean unaryFailed= false;
if (ctx != CastExprCtx.eNotBExpr) {
if (ctx == CastExprCtx.eDirectlyInBExpr) {
switch (LT(1)){
// ambiguity with unary operator
case IToken.tPLUS: case IToken.tMINUS:
Expand All @@ -1208,7 +1219,7 @@ protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileE
IToken markEnd= mark();
backup(mark);
try {
IASTExpression unary= unaryExpression(CastExprCtx.eNotBExpr);
IASTExpression unary= unaryExpression(CastExprCtx.eInBExpr, strat);
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
} catch (BacktrackException bt) {
backup(markEnd);
Expand All @@ -1218,20 +1229,21 @@ protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileE
}
try {
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
IASTExpression rhs= castExpression(ctx);
IASTExpression rhs= castExpression(ctx, strat);

CastAmbiguityMarker ca= null;
if (rhs instanceof CastAmbiguityMarker) {
ca= (CastAmbiguityMarker) rhs;
rhs= ca.getExpression();
assert !(rhs instanceof CastAmbiguityMarker);
}
IASTCastExpression result= buildCastExpression(IASTCastExpression.op_cast, typeId, rhs, startingOffset, calculateEndOffset(rhs));
IASTCastExpression result = buildCastExpression(IASTCastExpression.op_cast,
typeId, rhs, startingOffset, calculateEndOffset(rhs));
if (!unaryFailed && couldBeFunctionCall && rhs instanceof IASTCastExpression == false) {
IToken markEnd= mark();
backup(mark);
try {
IASTExpression expr= primaryExpression(ctx);
IASTExpression expr= primaryExpression(ctx, strat);
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, (IASTExpression[]) null);
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
Expand All @@ -1249,7 +1261,7 @@ protected final IASTExpression castExpression(CastExprCtx ctx) throws EndOfFileE
}
backup(mark);
}
return unaryExpression(ctx);
return unaryExpression(ctx, strat);
}

protected abstract IASTTranslationUnit getTranslationUnit();
Expand Down Expand Up @@ -1363,7 +1375,8 @@ private void addDeclaration(final IASTDeclarationListOwner parent, IASTDeclarati

abstract protected IASTExpression buildBinaryExpression(int operator, IASTExpression expr1, IASTInitializerClause expr2, int lastOffset);

private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpression expr, final IASTTypeId typeid, int unaryOperator, int unaryOpOffset) {
private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpression expr,
final IASTTypeId typeid, int unaryOperator, int unaryOpOffset) {
IASTUnaryExpression unary= nodeFactory.newUnaryExpression(unaryOperator, null);
((ASTNode) unary).setOffset(unaryOpOffset);
IASTCastExpression castExpr = buildCastExpression(IASTCastExpression.op_cast, typeid, unary, 0, 0);
Expand All @@ -1372,9 +1385,9 @@ private IASTExpression createCastVsBinaryExpressionAmbiguity(IASTBinaryExpressio
return result;
}

protected IASTExpression unaryExpression(int operator, CastExprCtx ctx) throws EndOfFileException, BacktrackException {
protected IASTExpression unaryExpression(int operator, CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
final IToken operatorToken= consume();
IASTExpression operand= castExpression(ctx);
IASTExpression operand= castExpression(ctx, strat);

CastAmbiguityMarker ca= null;
if (operand instanceof CastAmbiguityMarker) {
Expand Down Expand Up @@ -1814,13 +1827,12 @@ protected IASTASMDeclaration buildASMDirective(int offset, String assembly, int
return result;
}


protected IASTCastExpression buildCastExpression(int op, IASTTypeId typeId, IASTExpression operand, int offset, int endOffset) {
protected IASTCastExpression buildCastExpression(int op, IASTTypeId typeId,
IASTExpression operand, int offset, int endOffset) {
IASTCastExpression result = nodeFactory.newCastExpression(op, typeId, operand);
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
return result;
}


/**
* There are many ambiguities in C and C++ between expressions and declarations.
Expand Down Expand Up @@ -2173,7 +2185,7 @@ protected void throwBacktrack(IToken token) throws BacktrackException {
}

protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
int offset, int typeExprKind, int unaryExprKind, CastExprCtx ctx) throws BacktrackException, EndOfFileException {
int offset, int typeExprKind, int unaryExprKind, CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException {
IASTTypeId typeid;
IASTExpression expr= null;
IToken typeidLA= null;
Expand Down Expand Up @@ -2234,7 +2246,7 @@ protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprI
expr= expression();
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
} else {
expr= unaryExpression(ctx);
expr= unaryExpression(ctx, strat);
if (expr instanceof CastAmbiguityMarker) {
ca= (CastAmbiguityMarker) expr;
expr= ca.getExpression();
Expand Down

0 comments on commit 9a2e978

Please sign in to comment.