From 7b6d25b04cb86bbe6940d87dc73da8fbbebda5bd Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 4 Jun 2010 07:30:15 +0000 Subject: [PATCH] Properly disambiguate between an elaborated-type-specifier and a type-parameter within a template parameter list. Found by inspection. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105462 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseTemplate.cpp | 33 +++++++++++++++++++++++++++++++-- test/CXX/temp/temp.param/p2.cpp | 5 +++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index c87ddad4e9..5d248f1d77 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -341,8 +341,37 @@ Parser::ParseTemplateParameterList(unsigned Depth, /// \brief Determine whether the parser is at the start of a template /// type parameter. bool Parser::isStartOfTemplateTypeParameter() { - if (Tok.is(tok::kw_class)) - return true; + if (Tok.is(tok::kw_class)) { + // "class" may be the start of an elaborated-type-specifier or a + // type-parameter. Per C++ [temp.param]p3, we prefer the type-parameter. + switch (NextToken().getKind()) { + case tok::equal: + case tok::comma: + case tok::greater: + case tok::greatergreater: + case tok::ellipsis: + return true; + + case tok::identifier: + // This may be either a type-parameter or an elaborated-type-specifier. + // We have to look further. + break; + + default: + return false; + } + + switch (GetLookAheadToken(2).getKind()) { + case tok::equal: + case tok::comma: + case tok::greater: + case tok::greatergreater: + return true; + + default: + return false; + } + } if (Tok.isNot(tok::kw_typename)) return false; diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp index 41868c5c1a..fed6e9c266 100644 --- a/test/CXX/temp/temp.param/p2.cpp +++ b/test/CXX/temp/temp.param/p2.cpp @@ -14,4 +14,9 @@ template::type Value> struct Y1; // A storage class shall not be specified in a template-parameter declaration. template struct Z; // FIXME: expect an error +// Make sure that we properly disambiguate non-type template parameters that +// start with 'class'. +class X1 { }; +template struct Y2 { }; + // FIXME: add the example from p2 -- 2.40.0