[cfe-commits] r89532 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseTemplate.cpp test/CXX/temp/temp.param/p2.cpp

Douglas Gregor dgregor at apple.com
Fri Nov 20 18:07:56 PST 2009


Author: dgregor
Date: Fri Nov 20 20:07:55 2009
New Revision: 89532

URL: http://llvm.org/viewvc/llvm-project?rev=89532&view=rev
Log:
Implement C++ [temp.param]p2 correctly, looking ahead when we see a
"typename" parameter to distinguish between non-type and type template
parameters. Fixes the actual bug in PR5559.

Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/test/CXX/temp/temp.param/p2.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=89532&r1=89531&r2=89532&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Fri Nov 20 20:07:55 2009
@@ -1353,6 +1353,7 @@
                                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);

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=89532&r1=89531&r2=89532&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri Nov 20 20:07:55 2009
@@ -333,6 +333,40 @@
   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 @@
 ///         '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);

Modified: cfe/trunk/test/CXX/temp/temp.param/p2.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.param/p2.cpp?rev=89532&r1=89531&r2=89532&view=diff

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.param/p2.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.param/p2.cpp Fri Nov 20 20:07:55 2009
@@ -8,7 +8,8 @@
 
 // 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





More information about the cfe-commits mailing list