Improve diagnostic for missing comma in template parameter list.

Given 'typename T typename U', we would correctly diagnose the missing
comma, but incorrectly disambiguate the first parameter as being a
non-type parameter and complain that the 'T' is not a qualified-id.

See also gcc.gnu.org/PR86998.

llvm-svn: 340074
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 063f7cc..5af5437 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -425,7 +425,9 @@
     }
   }
 
-  if (Tok.isNot(tok::kw_typename))
+  // 'typedef' is a reasonably-common typo/thinko for 'typename', and is
+  // ill-formed otherwise.
+  if (Tok.isNot(tok::kw_typename) && Tok.isNot(tok::kw_typedef))
     return false;
 
   // C++ [temp.param]p2:
@@ -448,6 +450,13 @@
   case tok::ellipsis:
     return true;
 
+  case tok::kw_typename:
+  case tok::kw_typedef:
+  case tok::kw_class:
+    // These indicate that a comma was missed after a type parameter, not that
+    // we have found a non-type parameter.
+    return true;
+
   default:
     return false;
   }
@@ -469,26 +478,25 @@
 ///         'template' '<' template-parameter-list '>' 'class' identifier[opt]
 ///               = id-expression
 NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
-  if (isStartOfTemplateTypeParameter())
-    return ParseTypeParameter(Depth, Position);
+  if (isStartOfTemplateTypeParameter()) {
+    // Is there just a typo in the input code? ('typedef' instead of 'typename')
+    if (Tok.is(tok::kw_typedef)) {
+      Diag(Tok.getLocation(), diag::err_expected_template_parameter);
 
-  if (Tok.is(tok::kw_template))
-    return ParseTemplateTemplateParameter(Depth, Position);
+      Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
+          << FixItHint::CreateReplacement(CharSourceRange::getCharRange(
+                                              Tok.getLocation(), Tok.getEndLoc()),
+                                          "typename");
 
-  // Is there just a typo in the input code? ('typedef' instead of 'typename')
-  if (Tok.is(tok::kw_typedef)) {
-    Diag(Tok.getLocation(), diag::err_expected_template_parameter);
-
-    Diag(Tok.getLocation(), diag::note_meant_to_use_typename)
-        << FixItHint::CreateReplacement(CharSourceRange::getCharRange(
-                                            Tok.getLocation(), Tok.getEndLoc()),
-                                        "typename");
-
-    Tok.setKind(tok::kw_typename);
+      Tok.setKind(tok::kw_typename);
+    }
 
     return ParseTypeParameter(Depth, Position);
   }
 
+  if (Tok.is(tok::kw_template))
+    return ParseTemplateTemplateParameter(Depth, Position);
+
   // If it's none of the above, then it must be a parameter declaration.
   // NOTE: This will pick up errors in the closure of the template parameter
   // list (e.g., template < ; Check here to implement >> style closures.