aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Parse/Parser.h1
-rw-r--r--lib/Parse/ParseTemplate.cpp40
-rw-r--r--test/CXX/temp/temp.param/p2.cpp3
3 files changed, 38 insertions, 6 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index f7ccccac09..814064a79e 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1353,6 +1353,7 @@ private:
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
TemplateParameterList &TemplateParams);
+ bool isStartOfTemplateTypeParameter();
DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position);
DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 5be4ca82f7..e655dedab4 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -333,6 +333,40 @@ Parser::ParseTemplateParameterList(unsigned Depth,
return true;
}
+/// \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.isNot(tok::kw_typename))
+ return false;
+
+ // C++ [temp.param]p2:
+ // There is no semantic difference between class and typename in a
+ // template-parameter. typename followed by an unqualified-id
+ // names a template type parameter. typename followed by a
+ // qualified-id denotes the type in a non-type
+ // parameter-declaration.
+ Token Next = NextToken();
+
+ // If we have an identifier, skip over it.
+ if (Next.getKind() == tok::identifier)
+ Next = GetLookAheadToken(2);
+
+ switch (Next.getKind()) {
+ case tok::equal:
+ case tok::comma:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::ellipsis:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/// ParseTemplateParameter - Parse a template-parameter (C++ [temp.param]).
///
/// template-parameter: [C++ temp.param]
@@ -348,12 +382,8 @@ Parser::ParseTemplateParameterList(unsigned Depth,
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
Parser::DeclPtrTy
Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
- if (Tok.is(tok::kw_class) ||
- (Tok.is(tok::kw_typename) &&
- // FIXME: Next token has not been annotated!
- NextToken().isNot(tok::annot_typename))) {
+ if (isStartOfTemplateTypeParameter())
return ParseTypeParameter(Depth, Position);
- }
if (Tok.is(tok::kw_template))
return ParseTemplateTemplateParameter(Depth, Position);
diff --git a/test/CXX/temp/temp.param/p2.cpp b/test/CXX/temp/temp.param/p2.cpp
index a402cf6f88..d40f99b58a 100644
--- a/test/CXX/temp/temp.param/p2.cpp
+++ b/test/CXX/temp/temp.param/p2.cpp
@@ -8,7 +8,8 @@ template<typename T> struct X;
// typename followed by aqualified-id denotes the type in a non-type
// parameter-declaration.
-// FIXME: template<typename T, typename T::type Value> struct Y;
+template<typename T, typename T::type Value> struct Y0;
+template<typename T, typename X<T>::type Value> struct Y1;
// A storage class shall not be specified in a template-parameter declaration.
template<static int Value> struct Z; // FIXME: expect an error