1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-03 14:25:37 +02:00

Bug 333285: Non-type template parameter with leading typename keyword.

This commit is contained in:
Markus Schorn 2011-01-07 11:16:33 +00:00
parent 3a300ec622
commit c3d083bf06
2 changed files with 119 additions and 88 deletions

View file

@ -5173,4 +5173,17 @@ public class AST2TemplateTests extends AST2BaseTest {
public void testSpecializationViaNotDirectlyEnclosingTemplate_Bug333186() throws Exception {
parseAndCheckBindings();
}
// template <typename T> struct A {
// typedef T type;
// };
// template <typename T> struct X {
// template <typename A<T>::type x> struct Y {};
// };
//
// struct C {};
// template <class C& c> class Z{};
public void testNonTypeTemplateParameterWithTypenameKeyword_Bug333186() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -1756,103 +1756,121 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
* request for a backtrack
*/
protected List<ICPPASTTemplateParameter> templateParameterList() throws BacktrackException, EndOfFileException {
// if we have gotten this far then we have a true template-declaration
// iterate through the template parameter list
List<ICPPASTTemplateParameter> returnValue = new ArrayList<ICPPASTTemplateParameter>(DEFAULT_PARM_LIST_SIZE);
List<ICPPASTTemplateParameter> result = new ArrayList<ICPPASTTemplateParameter>(DEFAULT_PARM_LIST_SIZE);
boolean needComma= false;
for (;;) {
final int lt1= LT(1);
if (lt1 == IToken.tGT || lt1 == IToken.tEOC || lt1 == IToken.tGT_in_SHIFTR)
return returnValue;
return result;
final int offset = LA(1).getOffset();
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
int type = (lt1 == IToken.t_class ? ICPPASTSimpleTypeTemplateParameter.st_class
: ICPPASTSimpleTypeTemplateParameter.st_typename);
boolean parameterPack= false;
IASTName identifierName = null;
IASTTypeId defaultValue = null;
int endOffset = consume().getEndOffset();
if (LT(1) == IToken.tELLIPSIS) {
parameterPack= true;
endOffset= consume().getOffset();
}
if (LT(1) == IToken.tIDENTIFIER) { // optional identifier
identifierName = identifier();
endOffset = calculateEndOffset(identifierName);
if (LT(1) == IToken.tASSIGN) { // optional = type-id
if (parameterPack)
throw backtrack;
consume();
defaultValue = typeId(DeclarationOptions.TYPEID); // type-id
endOffset = calculateEndOffset(defaultValue);
}
} else {
identifierName = nodeFactory.newName();
}
ICPPASTSimpleTypeTemplateParameter tpar = nodeFactory.newSimpleTypeTemplateParameter(type, identifierName, defaultValue);
tpar.setIsParameterPack(parameterPack);
setRange(tpar, offset, endOffset);
returnValue.add(tpar);
} else if (lt1 == IToken.t_template) {
boolean parameterPack= false;
IASTName identifierName = null;
IASTExpression defaultValue = null;
consume();
consume(IToken.tLT);
List<ICPPASTTemplateParameter> tparList = templateParameterList();
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
int endOffset = consume(IToken.t_class).getEndOffset();
if (LT(1) == IToken.tELLIPSIS) {
parameterPack= true;
endOffset= consume().getOffset();
}
if (LT(1) == IToken.tIDENTIFIER) { // optional identifier
identifierName = identifier();
endOffset = calculateEndOffset(identifierName);
if (LT(1) == IToken.tASSIGN) { // optional = type-id
if (parameterPack)
throw backtrack;
consume();
defaultValue = primaryExpression(CastExprCtx.eNotBExpr);
endOffset = calculateEndOffset(defaultValue);
}
} else {
identifierName = nodeFactory.newName();
}
ICPPASTTemplatedTypeTemplateParameter tpar = nodeFactory.newTemplatedTypeTemplateParameter(identifierName, defaultValue);
tpar.setIsParameterPack(parameterPack);
setRange(tpar, offset, endOffset);
for (int i = 0; i < tparList.size(); ++i) {
ICPPASTTemplateParameter p = tparList.get(i);
tpar.addTemplateParameter(p);
}
returnValue.add(tpar);
} else if (lt1 == IToken.tCOMMA) {
consume();
continue;
if (needComma) {
consume(IToken.tCOMMA);
} else {
boolean inTParList= fInTemplateParameterList;
try {
fInTemplateParameterList= true;
ICPPASTParameterDeclaration parm = parameterDeclaration();
returnValue.add(parm);
} finally {
fInTemplateParameterList= inTParList;
}
needComma= true;
}
ICPPASTTemplateParameter tpar= templateParameter();
result.add(tpar);
}
}
private ICPPASTTemplateParameter templateParameter() throws EndOfFileException, BacktrackException {
final int lt1= LT(1);
final IToken start= mark();
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
try {
int type = (lt1 == IToken.t_class ? ICPPASTSimpleTypeTemplateParameter.st_class
: ICPPASTSimpleTypeTemplateParameter.st_typename);
boolean parameterPack= false;
IASTName identifierName = null;
IASTTypeId defaultValue = null;
int endOffset = consume().getEndOffset();
if (LT(1) == IToken.tELLIPSIS) {
parameterPack= true;
endOffset= consume().getOffset();
}
if (LT(1) == IToken.tIDENTIFIER) { // optional identifier
identifierName = identifier();
endOffset = calculateEndOffset(identifierName);
if (LT(1) == IToken.tASSIGN) { // optional = type-id
if (parameterPack)
throw backtrack;
consume();
defaultValue = typeId(DeclarationOptions.TYPEID); // type-id
endOffset = calculateEndOffset(defaultValue);
}
} else {
identifierName = nodeFactory.newName();
}
// Check if followed by comma
switch (LT(1)) {
case IToken.tGT:
case IToken.tEOC:
case IToken.tGT_in_SHIFTR:
case IToken.tCOMMA:
ICPPASTSimpleTypeTemplateParameter tpar = nodeFactory.newSimpleTypeTemplateParameter(type, identifierName, defaultValue);
tpar.setIsParameterPack(parameterPack);
setRange(tpar, start.getOffset(), endOffset);
return tpar;
}
} catch (BacktrackException bt) {
}
// Can be a non-type template parameter, see bug 333285
backup(start);
} else if (lt1 == IToken.t_template) {
boolean parameterPack= false;
IASTName identifierName = null;
IASTExpression defaultValue = null;
consume();
consume(IToken.tLT);
List<ICPPASTTemplateParameter> tparList = templateParameterList();
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
int endOffset = consume(IToken.t_class).getEndOffset();
if (LT(1) == IToken.tELLIPSIS) {
parameterPack= true;
endOffset= consume().getOffset();
}
if (LT(1) == IToken.tIDENTIFIER) { // optional identifier
identifierName = identifier();
endOffset = calculateEndOffset(identifierName);
if (LT(1) == IToken.tASSIGN) { // optional = type-id
if (parameterPack)
throw backtrack;
consume();
defaultValue = primaryExpression(CastExprCtx.eNotBExpr);
endOffset = calculateEndOffset(defaultValue);
}
} else {
identifierName = nodeFactory.newName();
}
ICPPASTTemplatedTypeTemplateParameter tpar = nodeFactory.newTemplatedTypeTemplateParameter(identifierName, defaultValue);
tpar.setIsParameterPack(parameterPack);
setRange(tpar, start.getOffset(), endOffset);
for (int i = 0; i < tparList.size(); ++i) {
ICPPASTTemplateParameter p = tparList.get(i);
tpar.addTemplateParameter(p);
}
return tpar;
}
// Try non-type template parameter
boolean inTParList= fInTemplateParameterList;
try {
fInTemplateParameterList= true;
return parameterDeclaration();
} finally {
fInTemplateParameterList= inTParList;
}
}
/**
* The most abstract construct within a translationUnit : a declaration.