Semantic checking for class template declarations and
redeclarations. For example, checks that a class template
redeclaration has the same template parameters as previous
declarations.

Detangled class-template checking from ActOnTag, whose logic was
getting rather convoluted because it tried to handle C, C++, and C++
template semantics in one shot.

Made some inroads toward eliminating extraneous "declaration does not
declare anything" errors by adding an "error" type specifier.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63973 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 32b0011..d5af384 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -231,6 +231,13 @@
   return false;
 }
 
+bool DeclSpec::SetTypeSpecError() {
+  TypeSpecType = TST_error;
+  TypeRep = 0;
+  TSTLoc = SourceLocation();
+  return false;
+}
+
 bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
                            const LangOptions &Lang) {
   // Duplicates turn into warnings pre-C99.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index bbd5d4b..2ba1edc 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1213,8 +1213,7 @@
   else
     TK = Action::TK_Reference;
   DeclTy *TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TK, StartLoc,
-                                     SS, Name, NameLoc, Attr, 
-                                     Action::MultiTemplateParamsArg(Actions));
+                                     SS, Name, NameLoc, Attr);
   
   if (Tok.is(tok::l_brace))
     ParseEnumBody(StartLoc, TagDecl);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index b2b0d8f..59c086f 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -345,14 +345,17 @@
     return;
   }
 
-  // Create the tag portion of the class, possibly resulting in a template.
-  DeclTy *TagOrTempDecl
-    = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
-                       NameLoc, Attr,
-                       Action::MultiTemplateParamsArg(
-                         Actions,
-                         TemplateParams? &(*TemplateParams)[0] : 0,
-                         TemplateParams? TemplateParams->size() : 0));
+  // Create the tag portion of the class or class template.
+  DeclTy *TagOrTempDecl;
+  if (TemplateParams && TK != Action::TK_Reference)
+    TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc,
+                                               SS, Name, NameLoc, Attr,
+                       Action::MultiTemplateParamsArg(Actions, 
+                                                      &(*TemplateParams)[0],
+                                                      TemplateParams->size()));
+  else
+    TagOrTempDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name, 
+                                     NameLoc, Attr);
 
   // Parse the optional base clause (C++ only).
   if (getLang().CPlusPlus && Tok.is(tok::colon)) {
@@ -372,7 +375,9 @@
   }
 
   const char *PrevSpec = 0;
-  if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl))
+  if (!TagOrTempDecl)
+    DS.SetTypeSpecError();
+  else if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, TagOrTempDecl))
     Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
 }
 
@@ -731,7 +736,12 @@
   // Enter a scope for the class.
   ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
 
-  Actions.ActOnTagStartDefinition(CurScope, TagDecl);
+  if (TagDecl)
+    Actions.ActOnTagStartDefinition(CurScope, TagDecl);
+  else {
+    SkipUntil(tok::r_brace, false, false);
+    return;
+  }
 
   // C++ 11p3: Members of a class defined with the keyword class are private
   // by default. Members of a class defined with the keywords struct or union
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index e95c106..8836106 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -247,9 +247,9 @@
   // Handle the template <...> part.
   SourceLocation TemplateLoc = ConsumeToken();
   TemplateParameterList TemplateParams; 
-  SourceLocation LParenLoc, RParenLoc;
-  if(!ParseTemplateParameters(Depth + 1, TemplateParams, LParenLoc,
-                              RParenLoc)) {
+  SourceLocation LAngleLoc, RAngleLoc;
+  if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+                              RAngleLoc)) {
     return 0;
   }
 
@@ -288,8 +288,15 @@
     }
   }
 
+  TemplateParamsTy *ParamList = 
+    Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
+                                       TemplateLoc, LAngleLoc,
+                                       &TemplateParams[0], 
+                                       TemplateParams.size(),
+                                       RAngleLoc);
+
   return Actions.ActOnTemplateTemplateParameter(CurScope, TemplateLoc,
-                                                &TemplateParams, ParamName,
+                                                ParamList, ParamName,
                                                 NameLoc, Depth, Position);
 }