1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-29 11:55:40 +02:00

Simplify error-prone detection of end of template-args, bug 237045.

This commit is contained in:
Markus Schorn 2008-07-04 09:27:39 +00:00
parent 878d36c539
commit 236fe5b939
4 changed files with 377 additions and 580 deletions

View file

@ -46,18 +46,6 @@ public interface ICPPParserExtensionConfiguration {
*/ */
public boolean supportExtendedTemplateSyntax(); public boolean supportExtendedTemplateSyntax();
/**
* Support for (deprecated) GNU minimum and maximum operators ((<code>&lt;?</code> and
* <code>&gt;?</code>). If enabled, scanner extension support for those operators must
* also be enabled.
*
* @see IScannerExtensionConfiguration
* @see "http://gcc.gnu.org/onlinedocs/gcc/Deprecated-Features.html"
* @return <code>true</code> if support for the extension should be
* enabled
*/
public boolean supportMinAndMaxOperators();
/** /**
* Support for GNU extension "Data types for complex numbers". * Support for GNU extension "Data types for complex numbers".
* *
@ -157,15 +145,21 @@ public interface ICPPParserExtensionConfiguration {
*/ */
public boolean supportFunctionStyleAssembler(); public boolean supportFunctionStyleAssembler();
/**
* @deprecated configure extra keywords, via {@link IScannerExtensionConfiguration#getAdditionalKeywords()}
*/
@Deprecated
public boolean supportRestrictKeyword();
/** /**
* @deprecated use {@link #getBuiltinBindingsProvider()} instead. * @deprecated use {@link #getBuiltinBindingsProvider()} instead.
*/ */
@Deprecated @Deprecated
public boolean supportGCCOtherBuiltinSymbols(); public boolean supportGCCOtherBuiltinSymbols();
/**
* @deprecated use {@link IScannerExtensionConfiguration#supportMinAndMaxOperators()}, instead.
*/
@Deprecated
public boolean supportMinAndMaxOperators();
/**
* @deprecated configure extra keywords, via {@link IScannerExtensionConfiguration#getAdditionalKeywords()}
*/
@Deprecated
public boolean supportRestrictKeyword();
} }

View file

@ -65,6 +65,7 @@ import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTTypeIdExpression;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider; import org.eclipse.cdt.core.dom.parser.IBuiltinBindingsProvider;
import org.eclipse.cdt.core.dom.parser.ISourceCodeParser; import org.eclipse.cdt.core.dom.parser.ISourceCodeParser;
import org.eclipse.cdt.core.parser.AbstractParserLogService; import org.eclipse.cdt.core.parser.AbstractParserLogService;
@ -84,6 +85,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
* @author jcamelon * @author jcamelon
*/ */
public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser { public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
protected static int parseCount = 0;
protected final AbstractParserLogService log; protected final AbstractParserLogService log;
protected final IScanner scanner; protected final IScanner scanner;
protected final ParserMode mode; protected final ParserMode mode;
@ -106,6 +110,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected IToken declarationMark; protected IToken declarationMark;
protected IToken currToken; protected IToken currToken;
protected int eofOffset; protected int eofOffset;
protected boolean onTopInTemplateArgs= false;
protected boolean isCancelled = false;
protected boolean parsePassed = true; protected boolean parsePassed = true;
protected int backtrackCount = 0; protected int backtrackCount = 0;
protected BacktrackException backtrack = new BacktrackException(); protected BacktrackException backtrack = new BacktrackException();
@ -311,12 +318,6 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
} }
protected boolean isCancelled = false;
protected static final int DEFAULT_DESIGNATOR_LIST_SIZE = 4;
protected static int parseCount = 0;
protected void handleOffsetLimitException(OffsetLimitReachedException exception) throws EndOfFileException { protected void handleOffsetLimitException(OffsetLimitReachedException exception) throws EndOfFileException {
if (mode != ParserMode.COMPLETION_PARSE) if (mode != ParserMode.COMPLETION_PARSE)
throw new EndOfFileException(); throw new EndOfFileException();
@ -722,25 +723,25 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
} }
protected IASTExpression expression() throws BacktrackException, EndOfFileException { protected IASTExpression expression() throws BacktrackException, EndOfFileException {
IToken la = LA(1); IToken la = LA(1);
int startingOffset = la.getOffset(); int startingOffset = la.getOffset();
IASTExpression assignmentExpression = assignmentExpression(); IASTExpression assignmentExpression = assignmentExpression();
if (LT(1) != IToken.tCOMMA) if (LT(1) != IToken.tCOMMA)
return assignmentExpression; return assignmentExpression;
IASTExpressionList expressionList = createExpressionList(); IASTExpressionList expressionList = createExpressionList();
((ASTNode) expressionList).setOffset(startingOffset); ((ASTNode) expressionList).setOffset(startingOffset);
expressionList.addExpression(assignmentExpression); expressionList.addExpression(assignmentExpression);
int lastOffset = 0; int lastOffset = 0;
while (LT(1) == IToken.tCOMMA) { while (LT(1) == IToken.tCOMMA) {
consume(); consume();
IASTExpression secondExpression = assignmentExpression(); IASTExpression secondExpression = assignmentExpression();
expressionList.addExpression(secondExpression); expressionList.addExpression(secondExpression);
lastOffset = calculateEndOffset(secondExpression); lastOffset = calculateEndOffset(secondExpression);
} }
((ASTNode) expressionList).setLength(lastOffset - startingOffset); ((ASTNode) expressionList).setLength(lastOffset - startingOffset);
return expressionList; return expressionList;
} }
protected abstract IASTExpressionList createExpressionList(); protected abstract IASTExpressionList createExpressionList();
@ -748,15 +749,68 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
protected abstract IASTExpression assignmentExpression() protected abstract IASTExpression assignmentExpression()
throws BacktrackException, EndOfFileException; throws BacktrackException, EndOfFileException;
protected abstract IASTExpression relationalExpression() protected IASTExpression relationalExpression() throws BacktrackException, EndOfFileException {
throws BacktrackException, EndOfFileException; IASTExpression result= shiftExpression();
for (;;) {
int operator;
switch (LT(1)) {
case IToken.tGT:
if (onTopInTemplateArgs)
return result;
operator= IASTBinaryExpression.op_greaterThan;
break;
case IToken.tLT:
operator = IASTBinaryExpression.op_lessThan;
break;
case IToken.tLTEQUAL:
operator = IASTBinaryExpression.op_lessEqual;
break;
case IToken.tGTEQUAL:
operator = IASTBinaryExpression.op_greaterEqual;
break;
case IGCCToken.tMAX:
operator = IGPPASTBinaryExpression.op_max;
break;
case IGCCToken.tMIN:
operator = IGPPASTBinaryExpression.op_min;
break;
default:
return result;
}
consume();
IASTExpression rhs= shiftExpression();
result = buildBinaryExpression(operator, result, rhs, calculateEndOffset(rhs));
}
}
protected abstract IASTExpression multiplicativeExpression() protected abstract IASTExpression multiplicativeExpression()
throws BacktrackException, EndOfFileException; throws BacktrackException, EndOfFileException;
protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException; protected abstract IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException;
protected abstract IASTExpression castExpression() throws BacktrackException, EndOfFileException; protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLPAREN) {
final IToken mark = mark();
final int startingOffset = mark.getOffset();
consume();
if (!avoidCastExpressionByHeuristics()) {
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
try {
IASTExpression castExpression = castExpression();
return buildTypeIdUnaryExpression(IASTCastExpression.op_cast,
typeId, castExpression, startingOffset,
LT(1) == IToken.tEOC ? LA(1).getEndOffset() : calculateEndOffset(castExpression));
} catch (BacktrackException b) {
}
}
}
backup(mark);
}
return unaryExpression();
}
protected abstract IASTExpression unaryExpression() throws BacktrackException, EndOfFileException; protected abstract IASTExpression unaryExpression() throws BacktrackException, EndOfFileException;
@ -826,9 +880,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
return buildBinaryExpression(kind, lhs, rhs, calculateEndOffset(rhs)); return buildBinaryExpression(kind, lhs, rhs, calculateEndOffset(rhs));
} }
protected IASTExpression constantExpression() throws BacktrackException, protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
EndOfFileException { return conditionalExpression();
return conditionalExpression();
} }
protected IASTExpression logicalOrExpression() throws BacktrackException, protected IASTExpression logicalOrExpression() throws BacktrackException,

View file

@ -576,44 +576,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
return conditionalExpression; return conditionalExpression;
} }
@Override
protected IASTExpression relationalExpression() throws BacktrackException,
EndOfFileException {
IASTExpression firstExpression = shiftExpression();
for (;;) {
switch (LT(1)) {
case IToken.tGT:
case IToken.tLT:
case IToken.tLTEQUAL:
case IToken.tGTEQUAL:
int t = consume().getType();
IASTExpression secondExpression = shiftExpression();
int operator = 0;
switch (t) {
case IToken.tGT:
operator = IASTBinaryExpression.op_greaterThan;
break;
case IToken.tLT:
operator = IASTBinaryExpression.op_lessThan;
break;
case IToken.tLTEQUAL:
operator = IASTBinaryExpression.op_lessEqual;
break;
case IToken.tGTEQUAL:
operator = IASTBinaryExpression.op_greaterEqual;
break;
}
firstExpression = buildBinaryExpression(operator,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
default:
return firstExpression;
}
}
}
@Override @Override
protected IASTExpression multiplicativeExpression() protected IASTExpression multiplicativeExpression()
throws BacktrackException, EndOfFileException { throws BacktrackException, EndOfFileException {
@ -647,34 +609,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
} }
} }
/**
* castExpression : unaryExpression | "(" typeId ")" castExpression
*/
@Override
protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLPAREN) {
final IToken mark = mark();
final int startingOffset = mark.getOffset();
consume();
if (!avoidCastExpressionByHeuristics()) {
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
try {
IASTExpression castExpression = castExpression();
return buildTypeIdUnaryExpression(IASTCastExpression.op_cast,
typeId, castExpression, startingOffset,
LT(1) == IToken.tEOC ? LA(1).getEndOffset() : calculateEndOffset(castExpression));
} catch (BacktrackException b) {
}
}
}
backup(mark);
}
return unaryExpression();
}
@Override @Override
protected IASTExpression unaryExpression() throws EndOfFileException, protected IASTExpression unaryExpression() throws EndOfFileException,
BacktrackException { BacktrackException {

View file

@ -124,7 +124,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointer;
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTPointerToMember;
@ -166,58 +165,50 @@ import org.eclipse.cdt.internal.core.parser.token.TokenFactory;
* @author jcamelon * @author jcamelon
*/ */
public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
private static final int DEFAULT_PARM_LIST_SIZE = 4;
private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4;
private static final int DEFAULT_SIZE_EXCEPTIONS_LIST = 2;
private static final int DEFAULT_CONSTRUCTOR_CHAIN_LIST_SIZE = 4;
private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE= 4; private static final int DEFAULT_CATCH_HANDLER_LIST_SIZE= 4;
private static final int DEFAULT_PARAMETER_LIST_SIZE= 4; private static final int DEFAULT_PARAMETER_LIST_SIZE= 4;
private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {}; private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {};
private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED} private static enum DtorStrategy {PREFER_FUNCTION, PREFER_NESTED}
private ScopeStack templateIdScopes = new ScopeStack(); private final boolean allowCPPRestrict;
private final boolean supportExtendedTemplateSyntax;
private final boolean supportLongLong;
private final IIndex index;
protected CPPASTTranslationUnit translationUnit;
private int templateCount = 0; private int templateCount = 0;
private int functionBodyCount= 0; private int functionBodyCount= 0;
private int templateArgListCount= 0;
private int rejectLogicalOperatorInTemplateID= 0; private int rejectLogicalOperatorInTemplateID= 0;
private char[] currentClassName; private char[] currentClassName;
public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
IParserLogService log, ICPPParserExtensionConfiguration config) {
this(scanner, mode, log, config, null);
}
protected CPPASTTranslationUnit translationUnit; public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
IParserLogService log, ICPPParserExtensionConfiguration config,
private final static class ScopeStack { IIndex index) {
private int[] stack; super(scanner, log, mode,
config.supportStatementsInExpressions(),
private int index = -1; config.supportTypeofUnaryExpressions(),
config.supportAlignOfUnaryExpression(),
public ScopeStack() { config.supportKnRC(),
stack = new int[8]; config.supportAttributeSpecifiers(),
} config.supportDeclspecSpecifiers(),
config.getBuiltinBindingsProvider());
private void grow() { allowCPPRestrict = config.allowRestrictPointerOperators();
int[] newStack = new int[stack.length << 1]; supportExtendedTemplateSyntax = config.supportExtendedTemplateSyntax();
System.arraycopy(stack, 0, newStack, 0, stack.length); supportLongLong = config.supportLongLongs();
stack = newStack; supportParameterInfoBlock= config.supportParameterInfoBlock();
} supportExtendedSizeofOperator= config.supportExtendedSizeofOperator();
supportFunctionStyleAsm= config.supportFunctionStyleAssembler();
public void push(int i) { this.index= index;
if (++index == stack.length)
grow();
stack[index] = i;
}
public int pop() {
if (index >= 0)
return stack[index--];
return -1;
}
public int peek() {
if (index >= 0)
return stack[index];
return -1;
}
public int size() {
return index + 1;
}
} }
/** /**
@ -229,49 +220,68 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* @throws BacktrackException request a backtrack * @throws BacktrackException request a backtrack
*/ */
protected IToken consumeTemplateParameters(IToken previousLast) throws EndOfFileException, BacktrackException { protected IToken consumeTemplateParameters(IToken previousLast) throws EndOfFileException, BacktrackException {
int startingOffset = previousLast == null ? LA(1).getOffset() : previousLast.getOffset(); final int offset = previousLast == null ? LA(1).getOffset() : previousLast.getOffset();
IToken last = previousLast; // if there are no parameters then previousLast gets returned IToken last = previousLast; // if there are no parameters then previousLast gets returned
if (LT(1) == IToken.tLT) { if (LT(1) == IToken.tLT) {
last = consume(); last= consume();
int nk= 0;
// used to match brackets, parens and angle brackets int depth= 0;
// capable of recognizing cases like T<(a>b)> correctly int angleDepth= 0;
ScopeStack scopes = new ScopeStack();
scopes.push(IToken.tLT);
while(scopes.size() > 0) {
int top;
last = consume();
while(true) {
last= consume();
switch(last.getType()) { switch(last.getType()) {
case IToken.tGT: // '>' case IToken.tLT:
if(scopes.peek() == IToken.tLT) { if (nk == 0) {
scopes.pop(); angleDepth++;
} }
break;
case IToken.tGT:
if (nk == 0) {
if (--angleDepth < 0)
return last;
}
break; break;
case IToken.tRBRACKET: // ']' case IToken.tLBRACKET:
do { if (nk == 0) {
top = scopes.pop(); nk= IToken.tLBRACKET;
} while (scopes.size() > 0 && top == IToken.tLT); } else if (nk == IToken.tLBRACKET) {
if(top != IToken.tLBRACKET) depth++;
throwBacktrack(startingOffset, last.getEndOffset() - startingOffset); }
break; break;
case IToken.tRPAREN: // ')' case IToken.tRBRACKET:
do { if (nk == IToken.tLBRACKET) {
top = scopes.pop(); if (--depth < 0) {
} while (scopes.size() > 0 && top == IToken.tLT); nk= 0;
if(top != IToken.tLPAREN) }
throwBacktrack(startingOffset, last.getEndOffset() - startingOffset); }
break; break;
case IToken.tLT: // '<' case IToken.tLPAREN:
case IToken.tLBRACKET: // '[' if (nk == 0) {
case IToken.tLPAREN: // '(' nk= IToken.tLPAREN;
scopes.push(last.getType()); } else if (nk == IToken.tLPAREN) {
break; depth++;
}
break;
case IToken.tRPAREN:
if (nk == IToken.tLPAREN) {
if (--depth < 0) {
nk= 0;
}
}
break;
case IToken.tSEMI:
case IToken.tLBRACE:
case IToken.tRBRACE:
if (nk == 0) {
throwBacktrack(offset, last.getOffset() - offset);
}
break;
} }
} }
} }
@ -287,72 +297,63 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
boolean failed = false; boolean failed = false;
final int initialTemplateIdScopesSize= templateIdScopes.size(); while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
templateIdScopes.push(IToken.tLT); IToken argStart = mark();
try { IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
IToken argStart = mark();
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) { if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) {
// potentially a type-id - check for id-expression ambiguity // potentially a type-id - check for id-expression ambiguity
IToken typeIdEnd= mark(); IToken typeIdEnd= mark();
backup(argStart); backup(argStart);
try { try {
IASTExpression expression = assignmentExpression(); IASTExpression expression = assignmentExpression();
if(expression instanceof IASTIdExpression) { if(expression instanceof IASTIdExpression) {
IASTIdExpression idExpression= (IASTIdExpression) expression; IASTIdExpression idExpression= (IASTIdExpression) expression;
if(idExpression.getName() instanceof ICPPASTTemplateId) { if(idExpression.getName() instanceof ICPPASTTemplateId) {
/* /*
* A template-id cannot be used in an id-expression as a template argument. * A template-id cannot be used in an id-expression as a template argument.
* *
* 5.1-11 A template-id shall be used as an unqualified-id only as specified in * 5.1-11 A template-id shall be used as an unqualified-id only as specified in
* 14.7.2, 14.7, and 14.5.4. * 14.7.2, 14.7, and 14.5.4.
*/ */
throw backtrack;
}
if (mark() != typeIdEnd)
throw backtrack;
ICPPASTAmbiguousTemplateArgument ambiguity= createAmbiguousTemplateArgument();
ambiguity.addTypeId(typeId);
ambiguity.addIdExpression(idExpression);
list.add(ambiguity);
} else {
// prefer the typeId at this stage
throw backtrack; throw backtrack;
} }
} catch (BacktrackException e) {
// no ambiguity - its a type-id
list.add(typeId);
backup(typeIdEnd);
}
} else {
// not a type-id - try as expression
backup(argStart);
try {
IASTExpression expression = assignmentExpression();
list.add(expression);
} catch (BacktrackException e) {
backup(argStart);
}
}
if (LT(1) == IToken.tCOMMA) { if (mark() != typeIdEnd)
consume(); throw backtrack;
} else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
failed = true; ICPPASTAmbiguousTemplateArgument ambiguity= createAmbiguousTemplateArgument();
endOffset = LA(1).getEndOffset(); ambiguity.addTypeId(typeId);
break; ambiguity.addIdExpression(idExpression);
list.add(ambiguity);
} else {
// prefer the typeId at this stage
throw backtrack;
}
} catch (BacktrackException e) {
// no ambiguity - its a type-id
list.add(typeId);
backup(typeIdEnd);
}
} else {
// not a type-id - try as expression
backup(argStart);
try {
IASTExpression expression = assignmentExpression();
list.add(expression);
} catch (BacktrackException e) {
backup(argStart);
} }
} }
}
finally { if (LT(1) == IToken.tCOMMA) {
do { consume();
templateIdScopes.pop(); } else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
} while (templateIdScopes.size() > initialTemplateIdScopesSize); failed = true;
endOffset = LA(1).getEndOffset();
break;
}
} }
if (failed) if (failed)
throwBacktrack(startingOffset, endOffset - startingOffset); throwBacktrack(startingOffset, endOffset - startingOffset);
@ -459,7 +460,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
@Override @Override
protected IASTExpression conditionalExpression() throws BacktrackException, EndOfFileException { protected IASTExpression conditionalExpression() throws BacktrackException, EndOfFileException {
final IASTExpression expr= super.conditionalExpression(); final IASTExpression expr= super.conditionalExpression();
if (templateArgListCount > 0 && rejectLogicalOperatorInTemplateID > 0) { if (onTopInTemplateArgs && rejectLogicalOperatorInTemplateID > 0) {
// bug 104706, don't allow usage of logical operators in template argument lists. // bug 104706, don't allow usage of logical operators in template argument lists.
if (expr instanceof IASTConditionalExpression) { if (expr instanceof IASTConditionalExpression) {
final ASTNode node = (ASTNode) expr; final ASTNode node = (ASTNode) expr;
@ -482,7 +483,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (LT(1) == IToken.tLT) { if (LT(1) == IToken.tLT) {
IToken secondMark = mark(); IToken secondMark = mark();
consume(); consume();
templateArgListCount++; final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= true;
try { try {
// bug 229062: content assist after '<' needs to prefer to backtrack here // bug 229062: content assist after '<' needs to prefer to backtrack here
if (rejectLogicalOperatorInTemplateID == 1) { if (rejectLogicalOperatorInTemplateID == 1) {
@ -511,7 +513,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
argumentList.addSegment(null); argumentList.addSegment(null);
backup(secondMark); backup(secondMark);
} finally { } finally {
templateArgListCount--; onTopInTemplateArgs= wasOnTop;
} }
} else { } else {
argumentList.addSegment(null); argumentList.addSegment(null);
@ -727,6 +729,28 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return new CPPASTReferenceOperator(); return new CPPASTReferenceOperator();
} }
@Override
protected IASTExpression expression() throws EndOfFileException, BacktrackException {
final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= false;
try {
return super.expression();
} finally {
onTopInTemplateArgs= wasOnTop;
}
}
@Override
protected IASTExpression constantExpression() throws EndOfFileException, BacktrackException {
final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= false;
try {
return super.constantExpression();
} finally {
onTopInTemplateArgs= wasOnTop;
}
}
@Override @Override
protected IASTExpression assignmentExpression() throws EndOfFileException, protected IASTExpression assignmentExpression() throws EndOfFileException,
BacktrackException { BacktrackException {
@ -805,75 +829,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwExpression, throwToken.getOffset(), o); // fix for 95225 throwExpression, throwToken.getOffset(), o); // fix for 95225
} }
@Override
protected IASTExpression relationalExpression() throws BacktrackException, EndOfFileException {
IASTExpression firstExpression = shiftExpression();
for (;;) {
final int lt1 = LT(1);
switch (lt1) {
case IToken.tGT:
case IToken.tLT:
case IToken.tLTEQUAL:
case IToken.tGTEQUAL:
if (lt1 == IToken.tGT && templateIdScopes.size() > 0 && templateIdScopes.peek() == IToken.tLT)
return firstExpression;
IToken m = mark();
int t = consume().getType();
IASTExpression secondExpression = null;
try {
secondExpression = shiftExpression();
} catch (BacktrackException bte) {
backup(m);
return firstExpression;
}
int expressionKind = 0;
switch (t) {
case IToken.tGT:
expressionKind = IASTBinaryExpression.op_greaterThan;
break;
case IToken.tLT:
expressionKind = IASTBinaryExpression.op_lessThan;
break;
case IToken.tLTEQUAL:
expressionKind = IASTBinaryExpression.op_lessEqual;
break;
case IToken.tGTEQUAL:
expressionKind = IASTBinaryExpression.op_greaterEqual;
break;
}
firstExpression = buildBinaryExpression(expressionKind,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
default:
if (supportMinAndMaxOperators
&& (LT(1) == IGCCToken.tMIN || LT(1) == IGCCToken.tMAX)) {
int new_operator = 0;
switch (lt1) {
case IGCCToken.tMAX:
consume();
new_operator = IGPPASTBinaryExpression.op_max;
break;
case IGCCToken.tMIN:
consume();
new_operator = IGPPASTBinaryExpression.op_min;
}
secondExpression = shiftExpression();
firstExpression = buildBinaryExpression(new_operator,
firstExpression, secondExpression,
calculateEndOffset(secondExpression));
break;
}
return firstExpression;
}
}
}
@Override @Override
protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException { protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException {
IASTExpression firstExpression = pmExpression(); IASTExpression firstExpression = pmExpression();
@ -934,48 +889,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
} }
} }
/**
* castExpression : unaryExpression | "(" typeId ")" castExpression
*/
@Override
protected IASTExpression castExpression() throws EndOfFileException, BacktrackException {
if (LT(1) == IToken.tLPAREN) {
final IToken mark = mark();
final int startingOffset = mark.getOffset();
consume();
final int initialSize= templateIdScopes.size();
if (initialSize > 0)
templateIdScopes.push(IToken.tLPAREN);
try {
if (!avoidCastExpressionByHeuristics()) {
IASTTypeId typeId = typeId(DeclarationOptions.TYPEID);
if (typeId != null && LT(1) == IToken.tRPAREN) {
consume();
if (initialSize > 0) {
templateIdScopes.pop();
}
try {
IASTExpression castExpression = castExpression();
return buildTypeIdUnaryExpression(IASTCastExpression.op_cast,
typeId, castExpression, startingOffset,
calculateEndOffset(castExpression));
} catch (BacktrackException b) {
}
}
}
backup(mark);
}
finally {
while (templateIdScopes.size() > initialSize) {
templateIdScopes.pop();
}
}
}
return unaryExpression();
}
@Override @Override
protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException { protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException {
if (!canBeTypeSpecifier()) { if (!canBeTypeSpecifier()) {
@ -1305,17 +1218,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
break; break;
case IToken.t_typeid: case IToken.t_typeid:
int so = consume().getOffset(); int so = consume().getOffset();
if (templateIdScopes.size() > 0) { return parseTypeidInParenthesisOrUnaryExpression(true, so, ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid);
templateIdScopes.push(IToken.tLPAREN);
}
try {
return parseTypeidInParenthesisOrUnaryExpression(true, so, ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid);
}
finally {
if (templateIdScopes.size() > 0) {
templateIdScopes.pop();
}
}
default: default:
firstExpression = primaryExpression(); firstExpression = primaryExpression();
@ -1327,25 +1230,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
case IToken.tLBRACKET: case IToken.tLBRACKET:
// array access // array access
consume(); consume();
if (templateIdScopes.size() > 0) {
templateIdScopes.push(IToken.tLBRACKET);
}
int lastOffset; int lastOffset;
try { secondExpression = expression();
secondExpression = expression(); switch (LT(1)) {
switch (LT(1)) { case IToken.tRBRACKET:
case IToken.tRBRACKET: case IToken.tEOC:
case IToken.tEOC: lastOffset = consume().getEndOffset();
lastOffset = consume().getEndOffset(); break;
break; default:
default: throw backtrack;
throw backtrack;
}
}
finally {
if (templateIdScopes.size() > 0) {
templateIdScopes.pop();
}
} }
IASTArraySubscriptExpression s = createArraySubscriptExpression(); IASTArraySubscriptExpression s = createArraySubscriptExpression();
@ -1359,27 +1252,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// function call // function call
consume(); consume();
if (templateIdScopes.size() > 0) { if (LT(1) != IToken.tRPAREN)
templateIdScopes.push(IToken.tLPAREN); secondExpression = expression();
} else
try { secondExpression = null;
if (LT(1) != IToken.tRPAREN) switch (LT(1)) {
secondExpression = expression(); case IToken.tRPAREN:
else case IToken.tEOC:
secondExpression = null; lastOffset = consume().getEndOffset();
switch (LT(1)) { break;
case IToken.tRPAREN: default:
case IToken.tEOC: throw backtrack;
lastOffset = consume().getEndOffset();
break;
default:
throw backtrack;
}
}
finally {
if (templateIdScopes.size() > 0) {
templateIdScopes.pop();
}
} }
IASTFunctionCallExpression fce = createFunctionCallExpression(); IASTFunctionCallExpression fce = createFunctionCallExpression();
@ -1568,24 +1451,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return compoundStatementExpression(); return compoundStatementExpression();
} }
t = consume(); t = consume();
if (templateIdScopes.size() > 0) {
templateIdScopes.push(IToken.tLPAREN);
}
int finalOffset= 0; int finalOffset= 0;
IASTExpression lhs; IASTExpression lhs= expression();
try { if (LT(1) == IToken.tRPAREN) {
lhs = expression(); finalOffset = consume().getEndOffset();
if (LT(1) == IToken.tRPAREN) { } else {
finalOffset = consume().getEndOffset(); // missing parenthesis, assume it's there and keep going.
} else { finalOffset = LA(1).getOffset();
// missing parenthesis, assume it's there and keep going.
finalOffset = LA(1).getOffset();
}
}
finally {
if (templateIdScopes.size() > 0) {
templateIdScopes.pop();
}
} }
return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, t.getOffset(), finalOffset); return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, t.getOffset(), finalOffset);
case IToken.tIDENTIFIER: case IToken.tIDENTIFIER:
@ -1630,7 +1502,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
IToken start = consume(); IToken start = consume();
IToken end = null; IToken end = null;
if (start.getType() == IToken.tIDENTIFIER) if (start.getType() == IToken.tIDENTIFIER)
end = consumeTemplateParameters(null); end = consumeTemplateParameters(end);
while (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) { while (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) {
end = consume(); end = consume();
if (end.getType() == IToken.tIDENTIFIER) if (end.getType() == IToken.tIDENTIFIER)
@ -1688,57 +1560,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return result; return result;
} }
private final boolean allowCPPRestrict;
private final boolean supportExtendedTemplateSyntax;
private final boolean supportMinAndMaxOperators;
private final boolean supportLongLong;
private final IIndex index;
private static final int DEFAULT_PARM_LIST_SIZE = 4;
private static final int DEFAULT_POINTEROPS_LIST_SIZE = 4;
private static final int DEFAULT_SIZE_EXCEPTIONS_LIST = 2;
private static final int DEFAULT_CONSTRUCTOR_CHAIN_LIST_SIZE = 4;
/**
* This is the standard constructor that we expect the Parser to be
* instantiated with.
*
* @param mode
* TODO
*/
public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
IParserLogService log, ICPPParserExtensionConfiguration config) {
this(scanner, mode, log, config, null);
}
public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
IParserLogService log, ICPPParserExtensionConfiguration config,
IIndex index) {
super(scanner, log, mode,
config.supportStatementsInExpressions(),
config.supportTypeofUnaryExpressions(),
config.supportAlignOfUnaryExpression(),
config.supportKnRC(),
config.supportAttributeSpecifiers(),
config.supportDeclspecSpecifiers(),
config.getBuiltinBindingsProvider());
allowCPPRestrict = config.allowRestrictPointerOperators();
supportExtendedTemplateSyntax = config.supportExtendedTemplateSyntax();
supportMinAndMaxOperators = config.supportMinAndMaxOperators();
supportLongLong = config.supportLongLongs();
supportParameterInfoBlock= config.supportParameterInfoBlock();
supportExtendedSizeofOperator= config.supportExtendedSizeofOperator();
supportFunctionStyleAsm= config.supportFunctionStyleAssembler();
this.index= index;
}
/** /**
* The merger of using-declaration and using-directive in ANSI C++ grammar. * The merger of using-declaration and using-directive in ANSI C++ grammar.
* using-declaration: using typename? ::? nested-name-specifier * using-declaration: using typename? ::? nested-name-specifier
@ -1913,105 +1734,100 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
*/ */
protected IASTDeclaration templateDeclaration(DeclarationOptions option) throws EndOfFileException, protected IASTDeclaration templateDeclaration(DeclarationOptions option) throws EndOfFileException,
BacktrackException { BacktrackException {
IToken mark = mark(); ++templateCount;
IToken firstToken = null; try {
boolean exported = false; IToken mark = mark();
boolean encounteredExtraMod = false; IToken firstToken = null;
++templateCount; boolean exported = false;
if (LT(1) == IToken.t_export) { boolean encounteredExtraMod = false;
exported = true; if (LT(1) == IToken.t_export) {
firstToken = consume(); exported = true;
consume(IToken.t_template); firstToken = consume();
} else { consume(IToken.t_template);
if (supportExtendedTemplateSyntax) { } else {
switch (LT(1)) { if (supportExtendedTemplateSyntax) {
case IToken.t_static: switch (LT(1)) {
case IToken.t_extern: case IToken.t_static:
case IToken.t_inline: case IToken.t_extern:
firstToken = consume(); case IToken.t_inline:
consume(IToken.t_template); firstToken = consume();
encounteredExtraMod = true; consume(IToken.t_template);
break; encounteredExtraMod = true;
default: break;
firstToken = consume(IToken.t_template); default:
break; firstToken = consume(IToken.t_template);
} break;
} else }
firstToken = consume(IToken.t_template); } else
} firstToken = consume(IToken.t_template);
if (LT(1) != IToken.tLT) { }
// explicit-instantiation if (LT(1) != IToken.tLT) {
ICPPASTExplicitTemplateInstantiation templateInstantiation = null; // explicit-instantiation
if (encounteredExtraMod && supportExtendedTemplateSyntax) { ICPPASTExplicitTemplateInstantiation templateInstantiation = null;
IGPPASTExplicitTemplateInstantiation temp = createGnuTemplateInstantiation(); if (encounteredExtraMod && supportExtendedTemplateSyntax) {
switch (firstToken.getType()) { IGPPASTExplicitTemplateInstantiation temp = createGnuTemplateInstantiation();
case IToken.t_static: switch (firstToken.getType()) {
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_static); case IToken.t_static:
break; temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_static);
case IToken.t_extern: break;
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_extern); case IToken.t_extern:
break; temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_extern);
case IToken.t_inline: break;
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_inline); case IToken.t_inline:
break; temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_inline);
} break;
templateInstantiation = temp; }
} else templateInstantiation = temp;
templateInstantiation = createTemplateInstantiation(); } else {
try { templateInstantiation = createTemplateInstantiation();
IASTDeclaration d = declaration(option); }
((ASTNode) templateInstantiation).setOffsetAndLength(firstToken
.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
templateInstantiation.setDeclaration(d);
} finally {
--templateCount;
}
return templateInstantiation;
}
consume(); // check for LT made before
if (LT(1) == IToken.tGT) {
// explicit-specialization
consume();
ICPPASTTemplateSpecialization templateSpecialization = createTemplateSpecialization();
try {
IASTDeclaration d = declaration(option);
((ASTNode) templateSpecialization).setOffsetAndLength(
firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
templateSpecialization.setDeclaration(d);
} finally {
--templateCount;
}
return templateSpecialization;
}
try {
List<ICPPASTTemplateParameter> parms = templateParameterList();
consume(IToken.tGT);
ICPPASTTemplateDeclaration templateDecl = createTemplateDeclaration();
try
{
IASTDeclaration d = declaration(option); IASTDeclaration d = declaration(option);
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(), ((ASTNode) templateInstantiation).setOffsetAndLength(firstToken
calculateEndOffset(d) - firstToken.getOffset()); .getOffset(), calculateEndOffset(d) - firstToken.getOffset());
templateDecl.setExported(exported); templateInstantiation.setDeclaration(d);
templateDecl.setDeclaration(d); return templateInstantiation;
for (int i = 0; i < parms.size(); ++i) { }
ICPPASTTemplateParameter parm = parms.get(i); consume(); // check for LT made before
templateDecl.addTemplateParamter(parm); if (LT(1) == IToken.tGT) {
} // explicit-specialization
} consume();
finally
{
--templateCount;
}
return templateDecl; ICPPASTTemplateSpecialization templateSpecialization = createTemplateSpecialization();
} catch (BacktrackException bt) { IASTDeclaration d = declaration(option);
backup(mark); ((ASTNode) templateSpecialization).setOffsetAndLength(
throw bt; firstToken.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
} templateSpecialization.setDeclaration(d);
return templateSpecialization;
}
try {
final boolean wasOnTop= onTopInTemplateArgs;
onTopInTemplateArgs= true;
List<ICPPASTTemplateParameter> parms;
try {
parms = templateParameterList();
consume(IToken.tGT);
} finally {
onTopInTemplateArgs= wasOnTop;
}
ICPPASTTemplateDeclaration templateDecl = createTemplateDeclaration();
IASTDeclaration d = declaration(option);
((ASTNode) templateDecl).setOffsetAndLength(firstToken.getOffset(),
calculateEndOffset(d) - firstToken.getOffset());
templateDecl.setExported(exported);
templateDecl.setDeclaration(d);
for (int i = 0; i < parms.size(); ++i) {
ICPPASTTemplateParameter parm = parms.get(i);
templateDecl.addTemplateParamter(parm);
}
return templateDecl;
} catch (BacktrackException bt) {
backup(mark);
throw bt;
}
} finally {
templateCount--;
}
} }