mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-07 00:05:53 +02:00
Bug 333285: Non-type template parameter with leading typename keyword.
This commit is contained in:
parent
3a300ec622
commit
c3d083bf06
2 changed files with 119 additions and 88 deletions
|
@ -5173,4 +5173,17 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
public void testSpecializationViaNotDirectlyEnclosingTemplate_Bug333186() throws Exception {
|
public void testSpecializationViaNotDirectlyEnclosingTemplate_Bug333186() throws Exception {
|
||||||
parseAndCheckBindings();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1756,103 +1756,121 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
* request for a backtrack
|
* request for a backtrack
|
||||||
*/
|
*/
|
||||||
protected List<ICPPASTTemplateParameter> templateParameterList() throws BacktrackException, EndOfFileException {
|
protected List<ICPPASTTemplateParameter> templateParameterList() throws BacktrackException, EndOfFileException {
|
||||||
// if we have gotten this far then we have a true template-declaration
|
List<ICPPASTTemplateParameter> result = new ArrayList<ICPPASTTemplateParameter>(DEFAULT_PARM_LIST_SIZE);
|
||||||
// iterate through the template parameter list
|
boolean needComma= false;
|
||||||
List<ICPPASTTemplateParameter> returnValue = new ArrayList<ICPPASTTemplateParameter>(DEFAULT_PARM_LIST_SIZE);
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
final int lt1= LT(1);
|
final int lt1= LT(1);
|
||||||
if (lt1 == IToken.tGT || lt1 == IToken.tEOC || lt1 == IToken.tGT_in_SHIFTR)
|
if (lt1 == IToken.tGT || lt1 == IToken.tEOC || lt1 == IToken.tGT_in_SHIFTR)
|
||||||
return returnValue;
|
return result;
|
||||||
|
|
||||||
final int offset = LA(1).getOffset();
|
if (needComma) {
|
||||||
if (lt1 == IToken.t_class || lt1 == IToken.t_typename) {
|
consume(IToken.tCOMMA);
|
||||||
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;
|
|
||||||
} else {
|
} else {
|
||||||
boolean inTParList= fInTemplateParameterList;
|
needComma= true;
|
||||||
try {
|
|
||||||
fInTemplateParameterList= true;
|
|
||||||
ICPPASTParameterDeclaration parm = parameterDeclaration();
|
|
||||||
returnValue.add(parm);
|
|
||||||
} finally {
|
|
||||||
fInTemplateParameterList= inTParList;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
* The most abstract construct within a translationUnit : a declaration.
|
||||||
|
|
Loading…
Add table
Reference in a new issue