Implement parsing of nested-name-specifiers that involve template-ids, e.g.,

  std::vector<int>::allocator_type

When we parse a template-id that names a type, it will become either a
template-id annotation (which is a parsed representation of a
template-id that has not yet been through semantic analysis) or a
typename annotation (where semantic analysis has resolved the
template-id to an actual type), depending on the context. We only
produce a type in contexts where we know that we only need type
information, e.g., in a type specifier. Otherwise, we create a
template-id annotation that can later be "upgraded" by transforming it
into a typename annotation when the parser needs a type. This occurs,
for example, when we've parsed "std::vector<int>" above and then see
the '::' after it. However, it means that when writing something like
this:

  template<> class Outer::Inner<int> { ... };

We have two tokens to represent Outer::Inner<int>: one token for the
nested name specifier Outer::, and one template-id annotation token
for Inner<int>, which will be passed to semantic analysis to define
the class template specialization.

Most of the churn in the template tests in this patch come from an
improvement in our error recovery from ill-formed template-ids.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65467 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index e36bc40..3ef3f93 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -309,75 +309,42 @@
   
   // Parse the (optional) nested-name-specifier.
   CXXScopeSpec SS;
-  if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) {
-    // FIXME: can we get a class template specialization or
-    // template-id token here?
-    if (Tok.isNot(tok::identifier))
+  if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS))
+    if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
       Diag(Tok, diag::err_expected_ident);
-  }
-
-
-  // These variables encode the simple-template-id that we might end
-  // up parsing below. We don't translate this into a type
-  // automatically because (1) we want to create a separate
-  // declaration for each specialization, and (2) we want to retain
-  // more information about source locations that types provide.
-  DeclTy *Template = 0;
-  SourceLocation LAngleLoc, RAngleLoc;
-  TemplateArgList TemplateArgs;
-  TemplateArgIsTypeList TemplateArgIsType;
-  TemplateArgLocationList TemplateArgLocations;
-  ASTTemplateArgsPtr TemplateArgsPtr(Actions, 0, 0, 0);
-  
 
   // Parse the (optional) class name or simple-template-id.
   IdentifierInfo *Name = 0;
   SourceLocation NameLoc;
+  TemplateIdAnnotation *TemplateId = 0;
   if (Tok.is(tok::identifier)) {
     Name = Tok.getIdentifierInfo();
     NameLoc = ConsumeToken();
+  } else if (Tok.is(tok::annot_template_id)) {
+    TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    NameLoc = ConsumeToken();
 
-    if (Tok.is(tok::less)) {
-      // This is a simple-template-id.
-      Action::TemplateNameKind TNK 
-        = Actions.isTemplateName(*Name, CurScope, Template, &SS);
+    if (TemplateId->Kind != TNK_Class_template) {
+      // The template-name in the simple-template-id refers to
+      // something other than a class template. Give an appropriate
+      // error message and skip to the ';'.
+      SourceRange Range(NameLoc);
+      if (SS.isNotEmpty())
+        Range.setBegin(SS.getBeginLoc());
 
-      bool Invalid = false;
-
-      // Parse the enclosed template argument list.
-      if (TNK != Action::TNK_Non_template)
-        Invalid = ParseTemplateIdAfterTemplateName(Template, NameLoc,
-                                                   &SS, true, LAngleLoc, 
-                                                   TemplateArgs,
-                                                   TemplateArgIsType,
-                                                   TemplateArgLocations,
-                                                   RAngleLoc);
+      Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
+        << Name << static_cast<int>(TemplateId->Kind) << Range;
       
-      TemplateArgsPtr.reset(&TemplateArgs[0], &TemplateArgIsType[0],
-                            TemplateArgs.size());
-
-      if (TNK != Action::TNK_Class_template) {
-        // The template-name in the simple-template-id refers to
-        // something other than a class template. Give an appropriate
-        // error message and skip to the ';'.
-        SourceRange Range(NameLoc);
-        if (SS.isNotEmpty())
-          Range.setBegin(SS.getBeginLoc());
-        else if (!Invalid)
-          
-        Diag(LAngleLoc, diag::err_template_spec_syntax_non_template)
-          << Name << static_cast<int>(TNK) << Range;
-
-        DS.SetTypeSpecError();
-        SkipUntil(tok::semi, false, true);
-        return;
-      }
+      DS.SetTypeSpecError();
+      SkipUntil(tok::semi, false, true);
+      TemplateId->Destroy();
+      return;
     }
   }
 
   // There are three options here.  If we have 'struct foo;', then
   // this is a forward declaration.  If we have 'struct foo {...' or
-  // 'struct fo :...' then this is a definition. Otherwise we have
+  // 'struct foo :...' then this is a definition. Otherwise we have
   // something like 'struct foo xyz', a reference.
   Action::TagKind TK;
   if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))
@@ -387,35 +354,43 @@
   else
     TK = Action::TK_Reference;
 
-  if (!Name && TK != Action::TK_Definition) {
+  if (!Name && !TemplateId && TK != Action::TK_Definition) {
     // We have a declaration or reference to an anonymous class.
     Diag(StartLoc, diag::err_anon_type_definition)
       << DeclSpec::getSpecifierName(TagType);
 
     // Skip the rest of this declarator, up until the comma or semicolon.
     SkipUntil(tok::comma, true);
+
+    if (TemplateId)
+      TemplateId->Destroy();
     return;
   }
 
   // Create the tag portion of the class or class template.
   DeclTy *TagOrTempDecl;
-  if (Template && TK != Action::TK_Reference)
+  if (TemplateId && TK != Action::TK_Reference) {
     // Explicit specialization or class template partial
     // specialization. Let semantic analysis decide.
-
-    // FIXME: we want a source range covering the simple-template-id.
+    ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->getTemplateArgIsType(),
+                                       TemplateId->NumArgs);
     TagOrTempDecl 
       = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
-                                                 StartLoc, SS, /*Range*/
-                                                 Template, NameLoc, 
-                                                 LAngleLoc, TemplateArgsPtr,
-                                                 &TemplateArgLocations[0],
-                                                 RAngleLoc, Attr,
+                       StartLoc, SS,
+                       TemplateId->Template, 
+                       TemplateId->TemplateNameLoc, 
+                       TemplateId->LAngleLoc, 
+                       TemplateArgsPtr,
+                       TemplateId->getTemplateArgLocations(),
+                       TemplateId->RAngleLoc, 
+                       Attr,
                        Action::MultiTemplateParamsArg(Actions, 
                                     TemplateParams? &(*TemplateParams)[0] : 0,
                                  TemplateParams? TemplateParams->size() : 0));
-
-  else if (TemplateParams && TK != Action::TK_Reference)
+    TemplateId->Destroy();
+  } else if (TemplateParams && TK != Action::TK_Reference)
     TagOrTempDecl = Actions.ActOnClassTemplate(CurScope, TagType, TK, StartLoc,
                                                SS, Name, NameLoc, Attr,
                        Action::MultiTemplateParamsArg(Actions,