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.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;
|
||||
|
@ -5314,4 +5315,74 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -7102,12 +7102,12 @@ public class AST2Tests extends AST2BaseTest {
|
|||
// 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('(');
|
||||
}
|
||||
|
|
|
@ -89,6 +89,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
|||
* 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;
|
||||
|
@ -154,7 +157,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
* 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;
|
||||
|
@ -921,7 +924,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
* 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;
|
||||
|
@ -949,9 +952,21 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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) {
|
||||
|
@ -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;
|
||||
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;
|
||||
|
@ -1116,25 +1126,26 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
|
||||
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 {
|
||||
|
@ -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) {
|
||||
final IToken mark= mark();
|
||||
final int startingOffset= mark.getOffset();
|
||||
|
@ -1199,7 +1210,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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:
|
||||
|
@ -1208,7 +1219,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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);
|
||||
|
@ -1218,7 +1229,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
try {
|
||||
boolean couldBeFunctionCall= LT(1) == IToken.tLPAREN;
|
||||
IASTExpression rhs= castExpression(ctx);
|
||||
IASTExpression rhs= castExpression(ctx, strat);
|
||||
|
||||
CastAmbiguityMarker ca= null;
|
||||
if (rhs instanceof CastAmbiguityMarker) {
|
||||
|
@ -1226,12 +1237,13 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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);
|
||||
|
@ -1249,7 +1261,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
backup(mark);
|
||||
}
|
||||
return unaryExpression(ctx);
|
||||
return unaryExpression(ctx, strat);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
@ -1372,9 +1385,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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) {
|
||||
|
@ -1814,13 +1827,12 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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.
|
||||
|
@ -2173,7 +2185,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -2234,7 +2246,7 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
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();
|
||||
|
|
|
@ -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
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -467,7 +467,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
int lt1;
|
||||
int conditionCount= 0;
|
||||
BinaryOperator lastOperator= null;
|
||||
IASTExpression lastExpression= castExpression(CastExprCtx.eBExpr);
|
||||
IASTExpression lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null);
|
||||
loop: while (true) {
|
||||
lt1= LT(1);
|
||||
switch(lt1) {
|
||||
|
@ -564,7 +564,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
consume(); // consume operator
|
||||
lastExpression= castExpression(CastExprCtx.eBExpr); // next cast expression
|
||||
lastExpression= castExpression(CastExprCtx.eDirectlyInBExpr, null); // next cast expression
|
||||
}
|
||||
|
||||
// Check for incomplete conditional expression
|
||||
|
@ -581,38 +581,38 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
((ASTNode) result).setOffsetAndLength(o, lastOffset - o);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected IASTExpression unaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression unaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||
switch (LT(1)) {
|
||||
case IToken.tSTAR:
|
||||
return unaryExpression(IASTUnaryExpression.op_star, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_star, ctx, strat);
|
||||
case IToken.tAMPER:
|
||||
return unaryExpression(IASTUnaryExpression.op_amper, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_amper, ctx, strat);
|
||||
case IToken.tPLUS:
|
||||
return unaryExpression(IASTUnaryExpression.op_plus, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_plus, ctx, strat);
|
||||
case IToken.tMINUS:
|
||||
return unaryExpression(IASTUnaryExpression.op_minus, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_minus, ctx, strat);
|
||||
case IToken.tNOT:
|
||||
return unaryExpression(IASTUnaryExpression.op_not, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_not, ctx, strat);
|
||||
case IToken.tBITCOMPLEMENT:
|
||||
return unaryExpression(IASTUnaryExpression.op_tilde, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_tilde, ctx, strat);
|
||||
case IToken.tINCR:
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixIncr, ctx, strat);
|
||||
case IToken.tDECR:
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx);
|
||||
return unaryExpression(IASTUnaryExpression.op_prefixDecr, ctx, strat);
|
||||
case IToken.t_sizeof:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx);
|
||||
IASTTypeIdExpression.op_sizeof, IASTUnaryExpression.op_sizeof, ctx, strat);
|
||||
case IGCCToken.t___alignof__:
|
||||
return parseTypeidInParenthesisOrUnaryExpression(false, consume().getOffset(),
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx);
|
||||
IASTTypeIdExpression.op_alignof, IASTUnaryExpression.op_alignOf, ctx, strat);
|
||||
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;
|
||||
switch (LT(1)) {
|
||||
case IToken.tLPAREN:
|
||||
|
@ -632,11 +632,11 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
} catch (BacktrackException bt) {
|
||||
}
|
||||
backup(m);
|
||||
firstExpression= primaryExpression(ctx);
|
||||
firstExpression= primaryExpression(ctx, strat);
|
||||
break;
|
||||
|
||||
default:
|
||||
firstExpression = primaryExpression(ctx);
|
||||
firstExpression = primaryExpression(ctx, strat);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -748,7 +748,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected IASTExpression primaryExpression(CastExprCtx ctx) throws EndOfFileException, BacktrackException {
|
||||
protected IASTExpression primaryExpression(CastExprCtx ctx, ITemplateIdStrategy strat) throws EndOfFileException, BacktrackException {
|
||||
IToken t = null;
|
||||
IASTLiteralExpression literalExpression = null;
|
||||
switch (LT(1)) {
|
||||
|
@ -1114,7 +1114,7 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
simpleType= IASTSimpleDeclSpecifier.t_typeof;
|
||||
consume(IGCCToken.t_typeof);
|
||||
typeofExpression = parseTypeidInParenthesisOrUnaryExpression(false, LA(1).getOffset(),
|
||||
IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotBExpr);
|
||||
IASTTypeIdExpression.op_typeof, -1, CastExprCtx.eNotInBExpr, null);
|
||||
|
||||
encounteredTypename= true;
|
||||
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
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -14,6 +14,7 @@ import java.util.HashSet;
|
|||
import java.util.LinkedList;
|
||||
|
||||
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.IASTDeclaration;
|
||||
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.IASTFunctionDefinition;
|
||||
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.IASTParameterDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
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.ICPPASTTemplateId;
|
||||
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.cpp.semantics.CPPSemantics;
|
||||
|
@ -115,6 +119,18 @@ final class CPPASTAmbiguityResolver extends ASTVisitor {
|
|||
if (fRepopulate.remove(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
return parent.getTranslationUnit().getScope();
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
if (qname.getParent() instanceof ICPPASTFieldReference) {
|
||||
name= qname;
|
||||
parent= name.getParent();
|
||||
}
|
||||
} else if (i > 0) {
|
||||
if (data != null) {
|
||||
data.usesEnclosingScope= false;
|
||||
}
|
||||
|
@ -1111,7 +1114,9 @@ public class CPPVisitor extends ASTQueries {
|
|||
return scope;
|
||||
}
|
||||
}
|
||||
} else if (parent instanceof ICPPASTFieldReference) {
|
||||
}
|
||||
|
||||
if (parent instanceof ICPPASTFieldReference) {
|
||||
if (data != null) {
|
||||
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
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
|
@ -251,15 +251,27 @@ public class LookupData {
|
|||
}
|
||||
|
||||
public boolean qualified() {
|
||||
if (forceQualified) return true;
|
||||
if (astName == null) return false;
|
||||
if (astName.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY) return false;
|
||||
IASTNode p1 = astName.getParent();
|
||||
if (p1 instanceof ICPPASTQualifiedName) {
|
||||
final IASTName[] qnames = ((ICPPASTQualifiedName) p1).getNames();
|
||||
return qnames.length == 1 || qnames[0] != astName;
|
||||
if (forceQualified)
|
||||
return true;
|
||||
|
||||
IASTName n= astName;
|
||||
if (n == null || n.getPropertyInParent() == CPPSemantics.STRING_LOOKUP_PROPERTY)
|
||||
return false;
|
||||
|
||||
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() {
|
||||
|
|
|
@ -100,7 +100,7 @@ public class AddIncludeTest extends TestCase {
|
|||
|
||||
String file= createFileName(".expected");
|
||||
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) {
|
||||
|
|
Loading…
Add table
Reference in a new issue