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:
parent
878d36c539
commit
236fe5b939
4 changed files with 377 additions and 580 deletions
|
@ -46,18 +46,6 @@ public interface ICPPParserExtensionConfiguration {
|
||||||
*/
|
*/
|
||||||
public boolean supportExtendedTemplateSyntax();
|
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".
|
* 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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue