mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 341747: Ambiguity between template-id and binary expression.
This commit is contained in:
parent
ee055684b2
commit
9a2e97825b
12 changed files with 1156 additions and 336 deletions
|
@ -24,6 +24,7 @@ import org.eclipse.cdt.core.dom.ast.ASTTypeUtil;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
|
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.IASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
|
||||||
|
@ -5314,4 +5315,74 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
public void testPartialSpecAfterExplicitInst_339475() throws Exception {
|
public void testPartialSpecAfterExplicitInst_339475() throws Exception {
|
||||||
parseAndCheckBindings();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -7102,12 +7102,12 @@ public class AST2Tests extends AST2BaseTest {
|
||||||
// void f() {
|
// void f() {
|
||||||
// int a=
|
// int a=
|
||||||
public void testLargeExpression_294029() throws Exception {
|
public void testLargeExpression_294029() throws Exception {
|
||||||
// when running the test in a suite, it cannot handle more than 200 parenthesis.
|
// when running the test in a suite, it cannot handle more than 160 parenthesis.
|
||||||
// run as a single test it does > 600.
|
// run as a single test it does > 500.
|
||||||
sValidateCopy= false;
|
sValidateCopy= false;
|
||||||
StringBuilder buf= new StringBuilder();
|
StringBuilder buf= new StringBuilder();
|
||||||
buf.append(getAboveComment());
|
buf.append(getAboveComment());
|
||||||
final int depth= 200;
|
final int depth= 160;
|
||||||
for (int i = 0; i < depth; i++) {
|
for (int i = 0; i < depth; i++) {
|
||||||
buf.append('(');
|
buf.append('(');
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
||||||
* Base class for the c- and c++ parser.
|
* Base class for the c- and c++ parser.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
|
public interface ITemplateIdStrategy {
|
||||||
|
}
|
||||||
|
|
||||||
protected static class FoundAggregateInitializer extends Exception {
|
protected static class FoundAggregateInitializer extends Exception {
|
||||||
public final IASTDeclarator fDeclarator;
|
public final IASTDeclarator fDeclarator;
|
||||||
public final IASTDeclSpecifier fDeclSpec;
|
public final IASTDeclSpecifier fDeclSpec;
|
||||||
|
@ -154,7 +157,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
* Information about the context in which a cast-expression is parsed:
|
* 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.
|
* 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 enum ExprKind {eExpression, eAssignment, eConstant}
|
||||||
|
|
||||||
protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
|
protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
|
||||||
|
@ -921,7 +924,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
* Models a cast expression followed by an operator. Can be linked into a chain.
|
* 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.
|
* 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 fOperatorToken;
|
||||||
final int fLeftPrecedence;
|
final int fLeftPrecedence;
|
||||||
final int fRightPrecedence;
|
final int fRightPrecedence;
|
||||||
|
@ -949,9 +952,21 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
fExpression= expr;
|
fExpression= expr;
|
||||||
return e;
|
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;
|
BinaryOperator rightChain= null;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (leftChain == null) {
|
if (leftChain == null) {
|
||||||
|
@ -973,18 +988,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) throws BacktrackException {
|
private IASTExpression buildExpression(IASTExpression left, BinaryOperator operator) {
|
||||||
int op, unaryOp= 0;
|
int op, unaryOp= 0;
|
||||||
final IASTInitializerClause right= operator.fExpression;
|
final IASTInitializerClause right= operator.fExpression;
|
||||||
switch(operator.fOperatorToken) {
|
switch(operator.fOperatorToken) {
|
||||||
case IToken.tQUESTION:
|
case IToken.tQUESTION:
|
||||||
final IASTInitializerClause negative;
|
final IASTInitializerClause negative;
|
||||||
if (operator.fNext == null || operator.fNext.fOperatorToken != IToken.tCOLON) {
|
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;
|
negative= null;
|
||||||
} else {
|
} else {
|
||||||
negative= operator.fNext.fExpression;
|
negative= operator.fNext.fExpression;
|
||||||
|
@ -1116,25 +1126,26 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert false;
|
assert false;
|
||||||
ASTNode node= (ASTNode) left;
|
|
||||||
throwBacktrack(node.getOffset(), node.getLength());
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right));
|
IASTExpression result= buildBinaryExpression(op, left, right, calculateEndOffset(right));
|
||||||
final CastAmbiguityMarker am = operator.fAmbiguityMarker;
|
final CastAmbiguityMarker am = operator.fAmbiguityMarker;
|
||||||
if (am != null) {
|
if (am != null) {
|
||||||
assert unaryOp != 0;
|
if (unaryOp != 0) {
|
||||||
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
result = createCastVsBinaryExpressionAmbiguity((IASTBinaryExpression) result,
|
||||||
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
|
am.getTypeIdForCast(), unaryOp, am.getUnaryOperatorOffset());
|
||||||
|
} else {
|
||||||
|
assert false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression expression() throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression constantExpression() throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression unaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTExpression primaryExpression(CastExprCtx ctx) throws BacktrackException, EndOfFileException;
|
protected abstract IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws BacktrackException, EndOfFileException;
|
||||||
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException, BacktrackException;
|
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException, BacktrackException;
|
||||||
|
|
||||||
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
|
private final static class CastAmbiguityMarker extends ASTNode implements IASTExpression {
|
||||||
|
@ -1186,7 +1197,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if (LT(1) == IToken.tLPAREN) {
|
||||||
final IToken mark= mark();
|
final IToken mark= mark();
|
||||||
final int startingOffset= mark.getOffset();
|
final int startingOffset= mark.getOffset();
|
||||||
|
@ -1199,7 +1210,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
if (typeId != null && LT(1) == IToken.tRPAREN) {
|
||||||
consume();
|
consume();
|
||||||
boolean unaryFailed= false;
|
boolean unaryFailed= false;
|
||||||
if (ctx != CastExprCtx.eNotBExpr) {
|
if (ctx == CastExprCtx.eDirectlyInBExpr) {
|
||||||
switch (LT(1)){
|
switch (LT(1)){
|
||||||
// ambiguity with unary operator
|
// ambiguity with unary operator
|
||||||
case IToken.tPLUS: case IToken.tMINUS:
|
case IToken.tPLUS: case IToken.tMINUS:
|
||||||
|
@ -1208,7 +1219,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
IToken markEnd= mark();
|
IToken markEnd= mark();
|
||||||
backup(mark);
|
backup(mark);
|
||||||
try {
|
try {
|
||||||
IASTExpression unary= unaryExpression(CastExprCtx.eNotBExpr);
|
IASTExpression unary= unaryExpression(CastExprCtx.eInBExpr, strat);
|
||||||
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
return new CastAmbiguityMarker(unary, typeId, operatorOffset);
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
backup(markEnd);
|
backup(markEnd);
|
||||||
|
@ -1218,7 +1229,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
||||||
IASTExpression rhs= castExpression(ctx);
|
IASTExpression rhs= castExpression(ctx, strat);
|
||||||
|
|
||||||
CastAmbiguityMarker ca= null;
|
CastAmbiguityMarker ca= null;
|
||||||
if (rhs instanceof CastAmbiguityMarker) {
|
if (rhs instanceof CastAmbiguityMarker) {
|
||||||
|
@ -1226,12 +1237,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
rhs= ca.getExpression();
|
rhs= ca.getExpression();
|
||||||
assert !(rhs instanceof CastAmbiguityMarker);
|
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) {
|
if (!unaryFailed && couldBeFunctionCall && rhs instanceof IASTCastExpression == false) {
|
||||||
IToken markEnd= mark();
|
IToken markEnd= mark();
|
||||||
backup(mark);
|
backup(mark);
|
||||||
try {
|
try {
|
||||||
IASTExpression expr= primaryExpression(ctx);
|
IASTExpression expr= primaryExpression(ctx, strat);
|
||||||
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, (IASTExpression[]) null);
|
IASTFunctionCallExpression fcall = nodeFactory.newFunctionCallExpression(expr, (IASTExpression[]) null);
|
||||||
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
IASTAmbiguousExpression ambiguity = createAmbiguousCastVsFunctionCallExpression(result, fcall);
|
||||||
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
((ASTNode) ambiguity).setOffsetAndLength((ASTNode) result);
|
||||||
|
@ -1249,7 +1261,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
backup(mark);
|
backup(mark);
|
||||||
}
|
}
|
||||||
return unaryExpression(ctx);
|
return unaryExpression(ctx, strat);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract IASTTranslationUnit getTranslationUnit();
|
protected abstract IASTTranslationUnit getTranslationUnit();
|
||||||
|
@ -1363,7 +1375,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
|
|
||||||
abstract protected IASTExpression buildBinaryExpression(int operator, IASTExpression expr1, IASTInitializerClause expr2, int lastOffset);
|
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);
|
IASTUnaryExpression unary= nodeFactory.newUnaryExpression(unaryOperator, null);
|
||||||
((ASTNode) unary).setOffset(unaryOpOffset);
|
((ASTNode) unary).setOffset(unaryOpOffset);
|
||||||
IASTCastExpression castExpr = buildCastExpression(IASTCastExpression.op_cast, typeid, unary, 0, 0);
|
IASTCastExpression castExpr = buildCastExpression(IASTCastExpression.op_cast, typeid, unary, 0, 0);
|
||||||
|
@ -1372,9 +1385,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return result;
|
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();
|
final IToken operatorToken= consume();
|
||||||
IASTExpression operand= castExpression(ctx);
|
IASTExpression operand= castExpression(ctx, strat);
|
||||||
|
|
||||||
CastAmbiguityMarker ca= null;
|
CastAmbiguityMarker ca= null;
|
||||||
if (operand instanceof CastAmbiguityMarker) {
|
if (operand instanceof CastAmbiguityMarker) {
|
||||||
|
@ -1814,14 +1827,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IASTCastExpression buildCastExpression(int op, IASTTypeId typeId,
|
||||||
protected IASTCastExpression buildCastExpression(int op, IASTTypeId typeId, IASTExpression operand, int offset, int endOffset) {
|
IASTExpression operand, int offset, int endOffset) {
|
||||||
IASTCastExpression result = nodeFactory.newCastExpression(op, typeId, operand);
|
IASTCastExpression result = nodeFactory.newCastExpression(op, typeId, operand);
|
||||||
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
|
((ASTNode) result).setOffsetAndLength(offset, endOffset - offset);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* There are many ambiguities in C and C++ between expressions and declarations.
|
* There are many ambiguities in C and C++ between expressions and declarations.
|
||||||
* This method will attempt to parse a statement as both an expression and a declaration,
|
* This method will attempt to parse a statement as both an expression and a declaration,
|
||||||
|
@ -2173,7 +2185,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IASTExpression parseTypeidInParenthesisOrUnaryExpression(boolean exprIsLimitedToParenthesis,
|
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;
|
IASTTypeId typeid;
|
||||||
IASTExpression expr= null;
|
IASTExpression expr= null;
|
||||||
IToken typeidLA= null;
|
IToken typeidLA= null;
|
||||||
|
@ -2234,7 +2246,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
||||||
expr= expression();
|
expr= expression();
|
||||||
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
endOffset2= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||||
} else {
|
} else {
|
||||||
expr= unaryExpression(ctx);
|
expr= unaryExpression(ctx, strat);
|
||||||
if (expr instanceof CastAmbiguityMarker) {
|
if (expr instanceof CastAmbiguityMarker) {
|
||||||
ca= (CastAmbiguityMarker) expr;
|
ca= (CastAmbiguityMarker) expr;
|
||||||
expr= ca.getExpression();
|
expr= ca.getExpression();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2005, 2010 IBM Corporation and others.
|
* Copyright (c) 2005, 2011 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -467,7 +467,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
int lt1;
|
int lt1;
|
||||||
int conditionCount= 0;
|
int conditionCount= 0;
|
||||||
BinaryOperator lastOperator= null;
|
BinaryOperator lastOperator= null;
|
||||||
IASTExpression lastExpression= castExpression(CastExprCtx.eBExpr);
|
IASTExpression lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null);
|
||||||
loop: while (true) {
|
loop: while (true) {
|
||||||
lt1= LT(1);
|
lt1= LT(1);
|
||||||
switch(lt1) {
|
switch(lt1) {
|
||||||
|
@ -564,7 +564,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
consume(); // consume operator
|
consume(); // consume operator
|
||||||
lastExpression= castExpression(CastExprCtx.eBExpr); // next cast expression
|
lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null); // next cast expression
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for incomplete conditional expression
|
// Check for incomplete conditional expression
|
||||||
|
@ -583,36 +583,36 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tSTAR:
|
case IToken.tSTAR:
|
||||||
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
return unaryExpression(IASTUnaryExpression.op_star, ctx, strat);
|
||||||
case IToken.tAMPER:
|
case IToken.tAMPER:
|
||||||
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat);
|
||||||
case IToken.tPLUS:
|
case IToken.tPLUS:
|
||||||
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat);
|
||||||
case IToken.tMINUS:
|
case IToken.tMINUS:
|
||||||
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
return unaryExpression(IASTUnaryExpression.op_minus, ctx, strat);
|
||||||
case IToken.tNOT:
|
case IToken.tNOT:
|
||||||
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
return unaryExpression(IASTUnaryExpression.op_not, ctx, strat);
|
||||||
case IToken.tBITCOMPLEMENT:
|
case IToken.tBITCOMPLEMENT:
|
||||||
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
return unaryExpression(IASTUnaryExpression.op_tilde, ctx, strat);
|
||||||
case IToken.tINCR:
|
case IToken.tINCR:
|
||||||
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx, strat);
|
||||||
case IToken.tDECR:
|
case IToken.tDECR:
|
||||||
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx, strat);
|
||||||
case IToken.t_sizeof:
|
case IToken.t_sizeof:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx, strat);
|
||||||
case IGCCToken.t___alignof__:
|
case IGCCToken.t___alignof__:
|
||||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx, strat);
|
||||||
default:
|
default:
|
||||||
return postfixExpression(ctx);
|
return postfixExpression(ctx, strat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IASTExpression postfixExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
private IASTExpression postfixExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
IASTExpression firstExpression = null;
|
IASTExpression firstExpression = null;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
case IToken.tLPAREN:
|
case IToken.tLPAREN:
|
||||||
|
@ -632,11 +632,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
} catch (BacktrackException bt) {
|
} catch (BacktrackException bt) {
|
||||||
}
|
}
|
||||||
backup(m);
|
backup(m);
|
||||||
firstExpression= primaryExpression(ctx);
|
firstExpression= primaryExpression(ctx, strat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
firstExpression = primaryExpression(ctx);
|
firstExpression = primaryExpression(ctx, strat);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,7 +748,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
protected IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||||
IToken t = null;
|
IToken t = null;
|
||||||
IASTLiteralExpression literalExpression = null;
|
IASTLiteralExpression literalExpression = null;
|
||||||
switch (LT(1)) {
|
switch (LT(1)) {
|
||||||
|
@ -1114,7 +1114,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
simpleType= IASTSimpleDeclSpecifier.t_typeof;
|
simpleType= IASTSimpleDeclSpecifier.t_typeof;
|
||||||
consume(IGCCToken.t_typeof);
|
consume(IGCCToken.t_typeof);
|
||||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, LA(1).getOffset(),
|
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, LA(1).getOffset(),
|
||||||
IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotBExpr);
|
IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotInBExpr, null);
|
||||||
|
|
||||||
encounteredTypename= true;
|
encounteredTypename= true;
|
||||||
endOffset= calculateEndOffset(typeofExpression);
|
endOffset= calculateEndOffset(typeofExpression);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2009, 2010 Wind River Systems, Inc. and others.
|
* Copyright (c) 2009, 2011 Wind River Systems, Inc. and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -14,6 +14,7 @@ import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
|
||||||
|
@ -21,11 +22,14 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
@ -115,6 +119,18 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
||||||
if (fRepopulate.remove(declaration)) {
|
if (fRepopulate.remove(declaration)) {
|
||||||
repopulateScope(declaration);
|
repopulateScope(declaration);
|
||||||
}
|
}
|
||||||
|
// Explicit and partial class template specializations need to be resolved right away,
|
||||||
|
// otherwise we fail to correctly resolve qualified names that depend on a partial specialization.
|
||||||
|
if (declaration instanceof IASTSimpleDeclaration) {
|
||||||
|
IASTSimpleDeclaration sdecl= (IASTSimpleDeclaration) declaration;
|
||||||
|
IASTDeclSpecifier declspec = sdecl.getDeclSpecifier();
|
||||||
|
if (declspec instanceof IASTCompositeTypeSpecifier && sdecl.getDeclarators().length == 0) {
|
||||||
|
IASTName name= ((IASTCompositeTypeSpecifier) declspec).getName().getLastName();
|
||||||
|
if (name instanceof ICPPASTTemplateId) {
|
||||||
|
name.resolveBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return PROCESS_CONTINUE;
|
return PROCESS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems, Inc. 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
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.BinaryOperator;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.NameOrTemplateIDVariants.BranchPoint;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.NameOrTemplateIDVariants.Variant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models expression variants for the ambiguity of a template id.
|
||||||
|
*/
|
||||||
|
public class CPPASTTemplateIDAmbiguity extends ASTAmbiguousNode implements IASTAmbiguousExpression {
|
||||||
|
|
||||||
|
private BinaryOperator fLastOperator;
|
||||||
|
private IASTInitializerClause fLastExpression;
|
||||||
|
private final BranchPoint fVariants;
|
||||||
|
private IASTNode[] fNodes;
|
||||||
|
private AbstractGNUSourceCodeParser fParser;
|
||||||
|
|
||||||
|
public CPPASTTemplateIDAmbiguity(AbstractGNUSourceCodeParser parser, BinaryOperator lastOperator, IASTInitializerClause expr,
|
||||||
|
BranchPoint variants) {
|
||||||
|
fParser= parser;
|
||||||
|
fLastOperator= lastOperator;
|
||||||
|
fLastExpression= expr;
|
||||||
|
fVariants= variants;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IASTNode resolveAmbiguity(ASTVisitor resolver) {
|
||||||
|
final IASTAmbiguityParent owner= (IASTAmbiguityParent) getParent();
|
||||||
|
IASTNode nodeToReplace= this;
|
||||||
|
|
||||||
|
// Try all variants and under the ones with correct template-ids select the one with
|
||||||
|
// the most template-ids.
|
||||||
|
int minOffset= -1;
|
||||||
|
for (BranchPoint v= fVariants; v != null; v= v.getNext()) {
|
||||||
|
Variant selected= null;
|
||||||
|
int bestCount= 0;
|
||||||
|
for (Variant q= v.getFirstVariant(); q != null ; q=q.getNext()) {
|
||||||
|
final IASTName[] templateNames = q.getTemplateNames();
|
||||||
|
if (templateNames.length > bestCount) {
|
||||||
|
// Don't check branch-points inside of a selected variant.
|
||||||
|
final IASTExpression expression = q.getExpression();
|
||||||
|
if (((ASTNode) expression).getOffset() < minOffset)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Setup the ast to use the alternative
|
||||||
|
owner.replace(nodeToReplace, expression);
|
||||||
|
nodeToReplace= expression;
|
||||||
|
|
||||||
|
// Handle nested ambiguities first
|
||||||
|
expression.accept(resolver);
|
||||||
|
|
||||||
|
int count= checkNames(templateNames);
|
||||||
|
if (count > bestCount) {
|
||||||
|
selected= q;
|
||||||
|
bestCount= count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the operator sequence
|
||||||
|
if (selected != null) {
|
||||||
|
minOffset= selected.getRightOffset();
|
||||||
|
BinaryOperator targetOp = selected.getTargetOperator();
|
||||||
|
if (targetOp == null) {
|
||||||
|
fLastExpression= selected.getExpression();
|
||||||
|
fLastOperator= v.getLeftOperator();
|
||||||
|
} else {
|
||||||
|
targetOp.exchange(selected.getExpression());
|
||||||
|
targetOp.setNext(v.getLeftOperator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Important: Before building the expression remove it from the owner
|
||||||
|
owner.replace(nodeToReplace, this);
|
||||||
|
|
||||||
|
// Create the expression and replace it
|
||||||
|
IASTExpression expr = fParser.buildExpression(fLastOperator, fLastExpression);
|
||||||
|
owner.replace(this, expr);
|
||||||
|
|
||||||
|
// Resolve further ambiguities within the new expression.
|
||||||
|
expr.accept(resolver);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int checkNames(final IASTName[] templateNames) {
|
||||||
|
int count= 0;
|
||||||
|
for (IASTName templateName : templateNames) {
|
||||||
|
if (templateName.getTranslationUnit() != null) {
|
||||||
|
IBinding b= templateName.resolveBinding();
|
||||||
|
if (b instanceof IProblemBinding) {
|
||||||
|
if (!containsFunctionTemplate(((IProblemBinding) b).getCandidateBindings()))
|
||||||
|
return -1;
|
||||||
|
count++;
|
||||||
|
} else if (b instanceof ICPPSpecialization || b instanceof ICPPTemplateDefinition
|
||||||
|
|| b instanceof ICPPConstructor
|
||||||
|
|| (b instanceof IFunction && b instanceof ICPPUnknownBinding)) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsFunctionTemplate(IBinding[] candidateBindings) {
|
||||||
|
for (IBinding cand : candidateBindings) {
|
||||||
|
if (cand instanceof ICPPFunctionTemplate ||
|
||||||
|
(cand instanceof ICPPFunction && cand instanceof ICPPSpecialization)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IASTNode[] getNodes() {
|
||||||
|
if (fNodes == null) {
|
||||||
|
List<IASTNode> nl= new ArrayList<IASTNode>();
|
||||||
|
nl.add(fLastExpression);
|
||||||
|
BinaryOperator op= fLastOperator;
|
||||||
|
while (op != null) {
|
||||||
|
nl.add(op.getExpression());
|
||||||
|
op= op.getNext();
|
||||||
|
}
|
||||||
|
Collections.reverse(nl);
|
||||||
|
fNodes= nl.toArray(new IASTNode[nl.size()]);
|
||||||
|
}
|
||||||
|
return fNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTExpression copy() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTExpression copy(CopyStyle style) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addExpression(IASTExpression e) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTExpression[] getExpressions() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,239 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems, Inc. 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
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.BinaryOperator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks variants of expressions due to the ambiguity between template-id and '<' operator.
|
||||||
|
*/
|
||||||
|
public class NameOrTemplateIDVariants {
|
||||||
|
/**
|
||||||
|
* A point where a '<' can be interpreted as less-than or as the angle-bracket of a template-id.
|
||||||
|
*/
|
||||||
|
static class BranchPoint {
|
||||||
|
private BranchPoint fNext;
|
||||||
|
private Variant fFirstVariant;
|
||||||
|
private final boolean fAllowAssignment;
|
||||||
|
private final int fConditionCount;
|
||||||
|
private final BinaryOperator fLeftOperator;
|
||||||
|
|
||||||
|
BranchPoint(BranchPoint next, Variant variant,
|
||||||
|
BinaryOperator left, boolean allowAssignment, int conditionCount) {
|
||||||
|
fNext= next;
|
||||||
|
fFirstVariant= variant;
|
||||||
|
fAllowAssignment= allowAssignment;
|
||||||
|
fConditionCount= conditionCount;
|
||||||
|
fLeftOperator= left;
|
||||||
|
// Set owner
|
||||||
|
while (variant != null) {
|
||||||
|
variant.fOwner= this;
|
||||||
|
variant= variant.getNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAllowAssignment() {
|
||||||
|
return fAllowAssignment;
|
||||||
|
}
|
||||||
|
public int getConditionCount() {
|
||||||
|
return fConditionCount;
|
||||||
|
}
|
||||||
|
public BinaryOperator getLeftOperator() {
|
||||||
|
return fLeftOperator;
|
||||||
|
}
|
||||||
|
public Variant getFirstVariant() {
|
||||||
|
return fFirstVariant;
|
||||||
|
}
|
||||||
|
public BranchPoint getNext() {
|
||||||
|
return fNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reverseVariants() {
|
||||||
|
Variant prev= null;
|
||||||
|
Variant curr= fFirstVariant;
|
||||||
|
while (curr != null) {
|
||||||
|
Variant next= curr.getNext();
|
||||||
|
curr.fNext= prev;
|
||||||
|
prev= curr;
|
||||||
|
curr= next;
|
||||||
|
}
|
||||||
|
fFirstVariant= prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant for a branch-point is a cast-expression that can be used within a binary expression.
|
||||||
|
*/
|
||||||
|
static class Variant {
|
||||||
|
private BranchPoint fOwner;
|
||||||
|
private Variant fNext;
|
||||||
|
private final IASTExpression fExpression;
|
||||||
|
private BinaryOperator fTargetOperator;
|
||||||
|
private final int fRightOffset;
|
||||||
|
private final IASTName[] fTemplateNames;
|
||||||
|
|
||||||
|
public Variant(Variant next, IASTExpression expr, IASTName[] templateNames, int rightOffset) {
|
||||||
|
fNext= next;
|
||||||
|
fExpression= expr;
|
||||||
|
fRightOffset= rightOffset;
|
||||||
|
fTemplateNames= templateNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BranchPoint getOwner() {
|
||||||
|
return fOwner;
|
||||||
|
}
|
||||||
|
public int getRightOffset() {
|
||||||
|
return fRightOffset;
|
||||||
|
}
|
||||||
|
public IASTName[] getTemplateNames() {
|
||||||
|
return fTemplateNames;
|
||||||
|
}
|
||||||
|
public Variant getNext() {
|
||||||
|
return fNext;
|
||||||
|
}
|
||||||
|
public IASTExpression getExpression() {
|
||||||
|
return fExpression;
|
||||||
|
}
|
||||||
|
public BinaryOperator getTargetOperator() {
|
||||||
|
return fTargetOperator;
|
||||||
|
}
|
||||||
|
public void setTargetOperator(BinaryOperator lastOperator) {
|
||||||
|
fTargetOperator= lastOperator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BranchPoint fFirst;
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return fFirst == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addBranchPoint(Variant variants, BinaryOperator left,
|
||||||
|
boolean allowAssignment, int conditionCount) {
|
||||||
|
fFirst= new BranchPoint(fFirst, variants, left, allowAssignment, conditionCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeVariants(int offset, BinaryOperator lastOperator) {
|
||||||
|
for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
|
||||||
|
for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
|
||||||
|
if (v.getTargetOperator() == null) {
|
||||||
|
if (offset == v.getRightOffset()) {
|
||||||
|
v.setTargetOperator(lastOperator);
|
||||||
|
} else if (offset > v.getRightOffset()) {
|
||||||
|
// Should not happen
|
||||||
|
assert false;
|
||||||
|
remove(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void discardOpenVariants(int operatorOffset) {
|
||||||
|
for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
|
||||||
|
for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
|
||||||
|
if (v.getTargetOperator() == null && v.getRightOffset() != operatorOffset) {
|
||||||
|
remove(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Variant findFallback(int operatorOffset) {
|
||||||
|
// Search for an open variant, with a small right offset and a large left offset
|
||||||
|
Variant best= null;
|
||||||
|
for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
|
||||||
|
for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
|
||||||
|
if (v.fRightOffset > operatorOffset) {
|
||||||
|
if (best == null || v.fRightOffset < best.fRightOffset) {
|
||||||
|
best= v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void useFallback(Variant fallback) {
|
||||||
|
// Discard variants that end within the fallback
|
||||||
|
int begin= ((ASTNode) fallback.getExpression()).getOffset();
|
||||||
|
int end= fallback.getRightOffset();
|
||||||
|
for (BranchPoint p = fFirst; p != null; p= p.getNext()) {
|
||||||
|
for (Variant v= p.getFirstVariant(); v != null; v= v.getNext()) {
|
||||||
|
if (v == fallback) {
|
||||||
|
remove(v);
|
||||||
|
} else {
|
||||||
|
int vend= v.getRightOffset();
|
||||||
|
if (vend > begin && vend < end)
|
||||||
|
remove(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void remove(Variant remove) {
|
||||||
|
final BranchPoint owner = remove.fOwner;
|
||||||
|
final Variant next = remove.getNext();
|
||||||
|
Variant prev= owner.getFirstVariant();
|
||||||
|
if (remove == prev) {
|
||||||
|
owner.fFirstVariant= next;
|
||||||
|
if (next == null) {
|
||||||
|
remove(owner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (prev != null) {
|
||||||
|
Variant n = prev.getNext();
|
||||||
|
if (n == remove) {
|
||||||
|
prev.fNext= next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove(BranchPoint remove) {
|
||||||
|
final BranchPoint next = remove.getNext();
|
||||||
|
if (remove == fFirst) {
|
||||||
|
fFirst= next;
|
||||||
|
} else {
|
||||||
|
BranchPoint prev= fFirst;
|
||||||
|
while (prev != null) {
|
||||||
|
BranchPoint n = prev.getNext();
|
||||||
|
if (n == remove) {
|
||||||
|
prev.fNext= next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prev= n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BranchPoint getOrderedBranchPoints() {
|
||||||
|
BranchPoint prev= null;
|
||||||
|
BranchPoint curr= fFirst;
|
||||||
|
while (curr != null) {
|
||||||
|
curr.reverseVariants();
|
||||||
|
BranchPoint next= curr.getNext();
|
||||||
|
curr.fNext= prev;
|
||||||
|
prev= curr;
|
||||||
|
curr= next;
|
||||||
|
}
|
||||||
|
fFirst= null;
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2011 Wind River Systems, Inc. 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
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import java.util.BitSet;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.AbstractGNUSourceCodeParser.ITemplateIdStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Governs backtracking through multiple variants due to the ambiguous meaning of '<'.
|
||||||
|
* @see NameOrTemplateIDVariants
|
||||||
|
*/
|
||||||
|
final class TemplateIdStrategy implements ITemplateIdStrategy {
|
||||||
|
private int fCurrentBranchPoint;
|
||||||
|
private BitSet fSimpleIDs;
|
||||||
|
private IASTName[] fTemplateNames;
|
||||||
|
|
||||||
|
public TemplateIdStrategy() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
fCurrentBranchPoint= -1;
|
||||||
|
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
||||||
|
if (fSimpleIDs != null) {
|
||||||
|
fSimpleIDs.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean ignoreTemplateID() {
|
||||||
|
fCurrentBranchPoint++;
|
||||||
|
return fSimpleIDs == null ? false : fSimpleIDs.get(fCurrentBranchPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTemplateName(IASTName name) {
|
||||||
|
fTemplateNames= ArrayUtil.append(fTemplateNames, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setNextAlternative() {
|
||||||
|
final int bp = fCurrentBranchPoint;
|
||||||
|
if (bp < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fCurrentBranchPoint= -1;
|
||||||
|
fTemplateNames= IASTName.EMPTY_NAME_ARRAY;
|
||||||
|
if (fSimpleIDs == null) {
|
||||||
|
fSimpleIDs= new BitSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a new branch as far right as possible.
|
||||||
|
final int len = fSimpleIDs.length();
|
||||||
|
if (len <= bp) {
|
||||||
|
fSimpleIDs.set(bp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int branch= Math.min(bp, len-2); branch>=0; branch--) {
|
||||||
|
if (!fSimpleIDs.get(branch)) {
|
||||||
|
fSimpleIDs.clear(branch+1, len);
|
||||||
|
fSimpleIDs.set(branch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName[] getTemplateNames() {
|
||||||
|
return ArrayUtil.trim(fTemplateNames);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1069,8 +1069,11 @@ public class CPPVisitor extends ASTQueries {
|
||||||
if (qname.isFullyQualified()) {
|
if (qname.isFullyQualified()) {
|
||||||
return parent.getTranslationUnit().getScope();
|
return parent.getTranslationUnit().getScope();
|
||||||
}
|
}
|
||||||
}
|
if (qname.getParent() instanceof ICPPASTFieldReference) {
|
||||||
if (i > 0) {
|
name= qname;
|
||||||
|
parent= name.getParent();
|
||||||
|
}
|
||||||
|
} else if (i > 0) {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
data.usesEnclosingScope= false;
|
data.usesEnclosingScope= false;
|
||||||
}
|
}
|
||||||
|
@ -1111,7 +1114,9 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (parent instanceof ICPPASTFieldReference) {
|
}
|
||||||
|
|
||||||
|
if (parent instanceof ICPPASTFieldReference) {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
data.usesEnclosingScope= false;
|
data.usesEnclosingScope= false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -251,15 +251,27 @@ public class LookupData {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean qualified() {
|
public boolean qualified() {
|
||||||
if (forceQualified) return true;
|
if (forceQualified)
|
||||||
if (astName == null) return false;
|
return true;
|
||||||
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
|
|
||||||
IASTNode p1 = astName.getParent();
|
IASTName n= astName;
|
||||||
if (p1 instanceof ICPPASTQualifiedName) {
|
if (n == null || n.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY)
|
||||||
final IASTName[] qnames = ((ICPPASTQualifiedName) p1).getNames();
|
return false;
|
||||||
return qnames.length == 1 || qnames[0] != astName;
|
|
||||||
|
IASTNode p = n.getParent();
|
||||||
|
if (p instanceof ICPPASTTemplateId) {
|
||||||
|
n= (IASTName) p;
|
||||||
|
p= p.getParent();
|
||||||
}
|
}
|
||||||
return p1 instanceof ICPPASTFieldReference;
|
if (p instanceof ICPPASTQualifiedName) {
|
||||||
|
final ICPPASTQualifiedName qname = (ICPPASTQualifiedName) p;
|
||||||
|
if (qname.isFullyQualified())
|
||||||
|
return true;
|
||||||
|
final IASTName[] qnames = qname.getNames();
|
||||||
|
if (qnames.length > 0 && qnames[0] != n)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return p instanceof ICPPASTFieldReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFunctionCall() {
|
public boolean isFunctionCall() {
|
||||||
|
|
|
@ -100,7 +100,7 @@ public class AddIncludeTest extends TestCase {
|
||||||
|
|
||||||
String file= createFileName(".expected");
|
String file= createFileName(".expected");
|
||||||
String expected= ResourceTestHelper.read(file).toString();
|
String expected= ResourceTestHelper.read(file).toString();
|
||||||
assertEquals(expected, fDocument.get());
|
assertEquals(expected.replace("\r\n", "\n"), fDocument.get().replace("\r\n", "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createFileName(String suffix) {
|
private String createFileName(String suffix) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue