mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 08:55:25 +02:00
Simplify error-prone detection of end of template-args, bug 237045.
This commit is contained in:
parent
878d36c539
commit
236fe5b939
4 changed files with 377 additions and 580 deletions
|
@ -46,18 +46,6 @@ public interface ICPPParserExtensionConfiguration {
|
|||
*/
|
||||
public boolean supportExtendedTemplateSyntax();
|
||||
|
||||
/**
|
||||
* Support for (deprecated) GNU minimum and maximum operators ((<code><?</code> and
|
||||
* <code>>?</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".
|
||||
*
|
||||
|
@ -157,15 +145,21 @@ public interface ICPPParserExtensionConfiguration {
|
|||
*/
|
||||
public boolean supportFunctionStyleAssembler();
|
||||
|
||||
/**
|
||||
* @deprecated configure extra keywords, via {@link IScannerExtensionConfiguration#getAdditionalKeywords()}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean supportRestrictKeyword();
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getBuiltinBindingsProvider()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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.IGNUASTTypeIdExpression;
|
||||
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.ISourceCodeParser;
|
||||
import org.eclipse.cdt.core.parser.AbstractParserLogService;
|
||||
|
@ -84,6 +85,9 @@ import org.eclipse.cdt.internal.core.parser.scanner.ILocationResolver;
|
|||
* @author jcamelon
|
||||
*/
|
||||
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 IScanner scanner;
|
||||
protected final ParserMode mode;
|
||||
|
@ -106,6 +110,9 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected IToken declarationMark;
|
||||
protected IToken currToken;
|
||||
protected int eofOffset;
|
||||
protected boolean onTopInTemplateArgs= false;
|
||||
|
||||
protected boolean isCancelled = false;
|
||||
protected boolean parsePassed = true;
|
||||
protected int backtrackCount = 0;
|
||||
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 {
|
||||
if (mode != ParserMode.COMPLETION_PARSE)
|
||||
throw new EndOfFileException();
|
||||
|
@ -722,25 +723,25 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
}
|
||||
|
||||
protected IASTExpression expression() throws BacktrackException, EndOfFileException {
|
||||
IToken la = LA(1);
|
||||
int startingOffset = la.getOffset();
|
||||
IASTExpression assignmentExpression = assignmentExpression();
|
||||
if (LT(1) != IToken.tCOMMA)
|
||||
return assignmentExpression;
|
||||
IToken la = LA(1);
|
||||
int startingOffset = la.getOffset();
|
||||
IASTExpression assignmentExpression = assignmentExpression();
|
||||
if (LT(1) != IToken.tCOMMA)
|
||||
return assignmentExpression;
|
||||
|
||||
IASTExpressionList expressionList = createExpressionList();
|
||||
((ASTNode) expressionList).setOffset(startingOffset);
|
||||
expressionList.addExpression(assignmentExpression);
|
||||
IASTExpressionList expressionList = createExpressionList();
|
||||
((ASTNode) expressionList).setOffset(startingOffset);
|
||||
expressionList.addExpression(assignmentExpression);
|
||||
|
||||
int lastOffset = 0;
|
||||
while (LT(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
IASTExpression secondExpression = assignmentExpression();
|
||||
expressionList.addExpression(secondExpression);
|
||||
lastOffset = calculateEndOffset(secondExpression);
|
||||
}
|
||||
((ASTNode) expressionList).setLength(lastOffset - startingOffset);
|
||||
return expressionList;
|
||||
int lastOffset = 0;
|
||||
while (LT(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
IASTExpression secondExpression = assignmentExpression();
|
||||
expressionList.addExpression(secondExpression);
|
||||
lastOffset = calculateEndOffset(secondExpression);
|
||||
}
|
||||
((ASTNode) expressionList).setLength(lastOffset - startingOffset);
|
||||
return expressionList;
|
||||
}
|
||||
|
||||
protected abstract IASTExpressionList createExpressionList();
|
||||
|
@ -748,15 +749,68 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
protected abstract IASTExpression assignmentExpression()
|
||||
throws BacktrackException, EndOfFileException;
|
||||
|
||||
protected abstract IASTExpression relationalExpression()
|
||||
throws BacktrackException, EndOfFileException;
|
||||
protected IASTExpression relationalExpression() 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()
|
||||
throws BacktrackException, 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;
|
||||
|
||||
|
@ -826,9 +880,8 @@ public abstract class AbstractGNUSourceCodeParser implements ISourceCodeParser {
|
|||
return buildBinaryExpression(kind, lhs, rhs, calculateEndOffset(rhs));
|
||||
}
|
||||
|
||||
protected IASTExpression constantExpression() throws BacktrackException,
|
||||
EndOfFileException {
|
||||
return conditionalExpression();
|
||||
protected IASTExpression constantExpression() throws BacktrackException, EndOfFileException {
|
||||
return conditionalExpression();
|
||||
}
|
||||
|
||||
protected IASTExpression logicalOrExpression() throws BacktrackException,
|
||||
|
|
|
@ -576,44 +576,6 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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
|
||||
protected IASTExpression multiplicativeExpression()
|
||||
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
|
||||
protected IASTExpression unaryExpression() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
|
|
|
@ -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.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||
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.IGPPASTPointer;
|
||||
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
|
||||
*/
|
||||
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_PARAMETER_LIST_SIZE= 4;
|
||||
private static final ASTVisitor EMPTY_VISITOR = new ASTVisitor() {};
|
||||
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 functionBodyCount= 0;
|
||||
private int templateArgListCount= 0;
|
||||
private int rejectLogicalOperatorInTemplateID= 0;
|
||||
private char[] currentClassName;
|
||||
|
||||
public GNUCPPSourceParser(IScanner scanner, ParserMode mode,
|
||||
IParserLogService log, ICPPParserExtensionConfiguration config) {
|
||||
this(scanner, mode, log, config, null);
|
||||
}
|
||||
|
||||
protected CPPASTTranslationUnit translationUnit;
|
||||
|
||||
private final static class ScopeStack {
|
||||
private int[] stack;
|
||||
|
||||
private int index = -1;
|
||||
|
||||
public ScopeStack() {
|
||||
stack = new int[8];
|
||||
}
|
||||
|
||||
private void grow() {
|
||||
int[] newStack = new int[stack.length << 1];
|
||||
System.arraycopy(stack, 0, newStack, 0, stack.length);
|
||||
stack = newStack;
|
||||
}
|
||||
|
||||
public void push(int i) {
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
supportLongLong = config.supportLongLongs();
|
||||
supportParameterInfoBlock= config.supportParameterInfoBlock();
|
||||
supportExtendedSizeofOperator= config.supportExtendedSizeofOperator();
|
||||
supportFunctionStyleAsm= config.supportFunctionStyleAssembler();
|
||||
this.index= index;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,49 +220,68 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
* @throws BacktrackException request a backtrack
|
||||
*/
|
||||
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
|
||||
|
||||
if (LT(1) == IToken.tLT) {
|
||||
last = consume();
|
||||
|
||||
// used to match brackets, parens and angle brackets
|
||||
// capable of recognizing cases like T<(a>b)> correctly
|
||||
ScopeStack scopes = new ScopeStack();
|
||||
scopes.push(IToken.tLT);
|
||||
|
||||
while(scopes.size() > 0) {
|
||||
int top;
|
||||
last = consume();
|
||||
last= consume();
|
||||
int nk= 0;
|
||||
int depth= 0;
|
||||
int angleDepth= 0;
|
||||
|
||||
while(true) {
|
||||
last= consume();
|
||||
switch(last.getType()) {
|
||||
case IToken.tGT: // '>'
|
||||
if(scopes.peek() == IToken.tLT) {
|
||||
scopes.pop();
|
||||
}
|
||||
case IToken.tLT:
|
||||
if (nk == 0) {
|
||||
angleDepth++;
|
||||
}
|
||||
break;
|
||||
case IToken.tGT:
|
||||
if (nk == 0) {
|
||||
if (--angleDepth < 0)
|
||||
return last;
|
||||
}
|
||||
break;
|
||||
|
||||
case IToken.tRBRACKET: // ']'
|
||||
do {
|
||||
top = scopes.pop();
|
||||
} while (scopes.size() > 0 && top == IToken.tLT);
|
||||
if(top != IToken.tLBRACKET)
|
||||
throwBacktrack(startingOffset, last.getEndOffset() - startingOffset);
|
||||
break;
|
||||
case IToken.tLBRACKET:
|
||||
if (nk == 0) {
|
||||
nk= IToken.tLBRACKET;
|
||||
} else if (nk == IToken.tLBRACKET) {
|
||||
depth++;
|
||||
}
|
||||
break;
|
||||
|
||||
case IToken.tRBRACKET:
|
||||
if (nk == IToken.tLBRACKET) {
|
||||
if (--depth < 0) {
|
||||
nk= 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IToken.tRPAREN: // ')'
|
||||
do {
|
||||
top = scopes.pop();
|
||||
} while (scopes.size() > 0 && top == IToken.tLT);
|
||||
if(top != IToken.tLPAREN)
|
||||
throwBacktrack(startingOffset, last.getEndOffset() - startingOffset);
|
||||
break;
|
||||
|
||||
case IToken.tLT: // '<'
|
||||
case IToken.tLBRACKET: // '['
|
||||
case IToken.tLPAREN: // '('
|
||||
scopes.push(last.getType());
|
||||
break;
|
||||
case IToken.tLPAREN:
|
||||
if (nk == 0) {
|
||||
nk= IToken.tLPAREN;
|
||||
} else if (nk == IToken.tLPAREN) {
|
||||
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;
|
||||
|
||||
final int initialTemplateIdScopesSize= templateIdScopes.size();
|
||||
templateIdScopes.push(IToken.tLT);
|
||||
try {
|
||||
while (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
||||
IToken argStart = mark();
|
||||
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)) {
|
||||
// potentially a type-id - check for id-expression ambiguity
|
||||
IToken typeIdEnd= mark();
|
||||
if(typeId != null && (LT(1)==IToken.tCOMMA || LT(1)==IToken.tGT || LT(1)==IToken.tEOC)) {
|
||||
// potentially a type-id - check for id-expression ambiguity
|
||||
IToken typeIdEnd= mark();
|
||||
|
||||
backup(argStart);
|
||||
try {
|
||||
IASTExpression expression = assignmentExpression();
|
||||
if(expression instanceof IASTIdExpression) {
|
||||
IASTIdExpression idExpression= (IASTIdExpression) expression;
|
||||
if(idExpression.getName() instanceof ICPPASTTemplateId) {
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
backup(argStart);
|
||||
try {
|
||||
IASTExpression expression = assignmentExpression();
|
||||
if(expression instanceof IASTIdExpression) {
|
||||
IASTIdExpression idExpression= (IASTIdExpression) expression;
|
||||
if(idExpression.getName() instanceof ICPPASTTemplateId) {
|
||||
/*
|
||||
* 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
|
||||
* 14.7.2, 14.7, and 14.5.4.
|
||||
*/
|
||||
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) {
|
||||
consume();
|
||||
} else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
||||
failed = true;
|
||||
endOffset = LA(1).getEndOffset();
|
||||
break;
|
||||
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;
|
||||
}
|
||||
} 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 {
|
||||
do {
|
||||
templateIdScopes.pop();
|
||||
} while (templateIdScopes.size() > initialTemplateIdScopesSize);
|
||||
|
||||
if (LT(1) == IToken.tCOMMA) {
|
||||
consume();
|
||||
} else if (LT(1) != IToken.tGT && LT(1) != IToken.tEOC) {
|
||||
failed = true;
|
||||
endOffset = LA(1).getEndOffset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (failed)
|
||||
throwBacktrack(startingOffset, endOffset - startingOffset);
|
||||
|
@ -459,7 +460,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
@Override
|
||||
protected IASTExpression conditionalExpression() throws BacktrackException, EndOfFileException {
|
||||
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.
|
||||
if (expr instanceof IASTConditionalExpression) {
|
||||
final ASTNode node = (ASTNode) expr;
|
||||
|
@ -482,7 +483,8 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (LT(1) == IToken.tLT) {
|
||||
IToken secondMark = mark();
|
||||
consume();
|
||||
templateArgListCount++;
|
||||
final boolean wasOnTop= onTopInTemplateArgs;
|
||||
onTopInTemplateArgs= true;
|
||||
try {
|
||||
// bug 229062: content assist after '<' needs to prefer to backtrack here
|
||||
if (rejectLogicalOperatorInTemplateID == 1) {
|
||||
|
@ -511,7 +513,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
argumentList.addSegment(null);
|
||||
backup(secondMark);
|
||||
} finally {
|
||||
templateArgListCount--;
|
||||
onTopInTemplateArgs= wasOnTop;
|
||||
}
|
||||
} else {
|
||||
argumentList.addSegment(null);
|
||||
|
@ -727,6 +729,28 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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
|
||||
protected IASTExpression assignmentExpression() throws EndOfFileException,
|
||||
BacktrackException {
|
||||
|
@ -805,75 +829,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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
|
||||
protected IASTExpression multiplicativeExpression() throws BacktrackException, EndOfFileException {
|
||||
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
|
||||
protected IASTTypeId typeId(DeclarationOptions option) throws EndOfFileException {
|
||||
if (!canBeTypeSpecifier()) {
|
||||
|
@ -1305,17 +1218,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
break;
|
||||
case IToken.t_typeid:
|
||||
int so = consume().getOffset();
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.push(IToken.tLPAREN);
|
||||
}
|
||||
try {
|
||||
return parseTypeidInParenthesisOrUnaryExpression(true, so, ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid);
|
||||
}
|
||||
finally {
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.pop();
|
||||
}
|
||||
}
|
||||
return parseTypeidInParenthesisOrUnaryExpression(true, so, ICPPASTTypeIdExpression.op_typeid, ICPPASTUnaryExpression.op_typeid);
|
||||
|
||||
default:
|
||||
firstExpression = primaryExpression();
|
||||
|
@ -1327,25 +1230,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
case IToken.tLBRACKET:
|
||||
// array access
|
||||
consume();
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.push(IToken.tLBRACKET);
|
||||
}
|
||||
int lastOffset;
|
||||
try {
|
||||
secondExpression = expression();
|
||||
switch (LT(1)) {
|
||||
case IToken.tRBRACKET:
|
||||
case IToken.tEOC:
|
||||
lastOffset = consume().getEndOffset();
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.pop();
|
||||
}
|
||||
secondExpression = expression();
|
||||
switch (LT(1)) {
|
||||
case IToken.tRBRACKET:
|
||||
case IToken.tEOC:
|
||||
lastOffset = consume().getEndOffset();
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
|
||||
IASTArraySubscriptExpression s = createArraySubscriptExpression();
|
||||
|
@ -1359,27 +1252,17 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
// function call
|
||||
consume();
|
||||
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.push(IToken.tLPAREN);
|
||||
}
|
||||
try {
|
||||
if (LT(1) != IToken.tRPAREN)
|
||||
secondExpression = expression();
|
||||
else
|
||||
secondExpression = null;
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
case IToken.tEOC:
|
||||
lastOffset = consume().getEndOffset();
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.pop();
|
||||
}
|
||||
if (LT(1) != IToken.tRPAREN)
|
||||
secondExpression = expression();
|
||||
else
|
||||
secondExpression = null;
|
||||
switch (LT(1)) {
|
||||
case IToken.tRPAREN:
|
||||
case IToken.tEOC:
|
||||
lastOffset = consume().getEndOffset();
|
||||
break;
|
||||
default:
|
||||
throw backtrack;
|
||||
}
|
||||
|
||||
IASTFunctionCallExpression fce = createFunctionCallExpression();
|
||||
|
@ -1568,24 +1451,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return compoundStatementExpression();
|
||||
}
|
||||
t = consume();
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.push(IToken.tLPAREN);
|
||||
}
|
||||
int finalOffset= 0;
|
||||
IASTExpression lhs;
|
||||
try {
|
||||
lhs = expression();
|
||||
if (LT(1) == IToken.tRPAREN) {
|
||||
finalOffset = consume().getEndOffset();
|
||||
} else {
|
||||
// missing parenthesis, assume it's there and keep going.
|
||||
finalOffset = LA(1).getOffset();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (templateIdScopes.size() > 0) {
|
||||
templateIdScopes.pop();
|
||||
}
|
||||
IASTExpression lhs= expression();
|
||||
if (LT(1) == IToken.tRPAREN) {
|
||||
finalOffset = consume().getEndOffset();
|
||||
} else {
|
||||
// missing parenthesis, assume it's there and keep going.
|
||||
finalOffset = LA(1).getOffset();
|
||||
}
|
||||
return buildUnaryExpression(IASTUnaryExpression.op_bracketedPrimary, lhs, t.getOffset(), finalOffset);
|
||||
case IToken.tIDENTIFIER:
|
||||
|
@ -1630,7 +1502,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
IToken start = consume();
|
||||
IToken end = null;
|
||||
if (start.getType() == IToken.tIDENTIFIER)
|
||||
end = consumeTemplateParameters(null);
|
||||
end = consumeTemplateParameters(end);
|
||||
while (LT(1) == IToken.tCOLONCOLON || LT(1) == IToken.tIDENTIFIER) {
|
||||
end = consume();
|
||||
if (end.getType() == IToken.tIDENTIFIER)
|
||||
|
@ -1688,57 +1560,6 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
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.
|
||||
* using-declaration: using typename? ::? nested-name-specifier
|
||||
|
@ -1913,105 +1734,100 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
*/
|
||||
protected IASTDeclaration templateDeclaration(DeclarationOptions option) throws EndOfFileException,
|
||||
BacktrackException {
|
||||
IToken mark = mark();
|
||||
IToken firstToken = null;
|
||||
boolean exported = false;
|
||||
boolean encounteredExtraMod = false;
|
||||
++templateCount;
|
||||
if (LT(1) == IToken.t_export) {
|
||||
exported = true;
|
||||
firstToken = consume();
|
||||
consume(IToken.t_template);
|
||||
} else {
|
||||
if (supportExtendedTemplateSyntax) {
|
||||
switch (LT(1)) {
|
||||
case IToken.t_static:
|
||||
case IToken.t_extern:
|
||||
case IToken.t_inline:
|
||||
firstToken = consume();
|
||||
consume(IToken.t_template);
|
||||
encounteredExtraMod = true;
|
||||
break;
|
||||
default:
|
||||
firstToken = consume(IToken.t_template);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
firstToken = consume(IToken.t_template);
|
||||
}
|
||||
if (LT(1) != IToken.tLT) {
|
||||
// explicit-instantiation
|
||||
ICPPASTExplicitTemplateInstantiation templateInstantiation = null;
|
||||
if (encounteredExtraMod && supportExtendedTemplateSyntax) {
|
||||
IGPPASTExplicitTemplateInstantiation temp = createGnuTemplateInstantiation();
|
||||
switch (firstToken.getType()) {
|
||||
case IToken.t_static:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_static);
|
||||
break;
|
||||
case IToken.t_extern:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_extern);
|
||||
break;
|
||||
case IToken.t_inline:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_inline);
|
||||
break;
|
||||
}
|
||||
templateInstantiation = temp;
|
||||
} else
|
||||
templateInstantiation = createTemplateInstantiation();
|
||||
try {
|
||||
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
|
||||
{
|
||||
++templateCount;
|
||||
try {
|
||||
IToken mark = mark();
|
||||
IToken firstToken = null;
|
||||
boolean exported = false;
|
||||
boolean encounteredExtraMod = false;
|
||||
if (LT(1) == IToken.t_export) {
|
||||
exported = true;
|
||||
firstToken = consume();
|
||||
consume(IToken.t_template);
|
||||
} else {
|
||||
if (supportExtendedTemplateSyntax) {
|
||||
switch (LT(1)) {
|
||||
case IToken.t_static:
|
||||
case IToken.t_extern:
|
||||
case IToken.t_inline:
|
||||
firstToken = consume();
|
||||
consume(IToken.t_template);
|
||||
encounteredExtraMod = true;
|
||||
break;
|
||||
default:
|
||||
firstToken = consume(IToken.t_template);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
firstToken = consume(IToken.t_template);
|
||||
}
|
||||
if (LT(1) != IToken.tLT) {
|
||||
// explicit-instantiation
|
||||
ICPPASTExplicitTemplateInstantiation templateInstantiation = null;
|
||||
if (encounteredExtraMod && supportExtendedTemplateSyntax) {
|
||||
IGPPASTExplicitTemplateInstantiation temp = createGnuTemplateInstantiation();
|
||||
switch (firstToken.getType()) {
|
||||
case IToken.t_static:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_static);
|
||||
break;
|
||||
case IToken.t_extern:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_extern);
|
||||
break;
|
||||
case IToken.t_inline:
|
||||
temp.setModifier(IGPPASTExplicitTemplateInstantiation.ti_inline);
|
||||
break;
|
||||
}
|
||||
templateInstantiation = temp;
|
||||
} else {
|
||||
templateInstantiation = createTemplateInstantiation();
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
--templateCount;
|
||||
}
|
||||
((ASTNode) templateInstantiation).setOffsetAndLength(firstToken
|
||||
.getOffset(), calculateEndOffset(d) - firstToken.getOffset());
|
||||
templateInstantiation.setDeclaration(d);
|
||||
return templateInstantiation;
|
||||
}
|
||||
consume(); // check for LT made before
|
||||
if (LT(1) == IToken.tGT) {
|
||||
// explicit-specialization
|
||||
consume();
|
||||
|
||||
return templateDecl;
|
||||
} catch (BacktrackException bt) {
|
||||
backup(mark);
|
||||
throw bt;
|
||||
}
|
||||
ICPPASTTemplateSpecialization templateSpecialization = createTemplateSpecialization();
|
||||
IASTDeclaration d = declaration(option);
|
||||
((ASTNode) templateSpecialization).setOffsetAndLength(
|
||||
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--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue