]> granicus.if.org Git - clang/commitdiff
Properly disambiguate between an elaborated-type-specifier and a
authorDouglas Gregor <dgregor@apple.com>
Fri, 4 Jun 2010 07:30:15 +0000 (07:30 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 4 Jun 2010 07:30:15 +0000 (07:30 +0000)
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
test/CXX/temp/temp.param/p2.cpp

index c87ddad4e9b31ca5a3a3ed2513787f3a06fb36d4..5d248f1d774e5d4f882638ca89d579f401bb4fa2 100644 (file)
@@ -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;
index 41868c5c1ac72215cb1fa40e54811ae3d6187757..fed6e9c266be8953c091531e626bd80828a22b5f 100644 (file)
@@ -14,4 +14,9 @@ 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
 
+// Make sure that we properly disambiguate non-type template parameters that
+// start with 'class'.
+class X1 { };
+template<class X1 *xptr> struct Y2 { };
+
 // FIXME: add the example from p2