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/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index ce15cf9..9cd5b97 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -95,7 +95,7 @@
   return false;
 }
 
-Action::TemplateNameKind 
+TemplateNameKind 
 MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
                               DeclTy *&TemplateDecl,
                               const CXXScopeSpec *SS) {
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6e68b20..bdd352f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -558,21 +558,8 @@
       TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), 
                                             Tok.getLocation(), CurScope);
 
-      if (TypeRep == 0 && getLang().CPlusPlus && NextToken().is(tok::less)) {
-        // If we have a template name, annotate the token and try again.
-        DeclTy *Template = 0;
-        if (TemplateNameKind TNK =
-              Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope,
-                                     Template)) {
-          AnnotateTemplateIdToken(Template, TNK, 0);
-          continue;
-        }
-      }
-
       if (TypeRep == 0)
         goto DoneWithDeclSpec;
-      
-
 
       // C++: If the identifier is actually the name of the class type
       // being defined and the next token is a '(', then this is a
@@ -610,6 +597,25 @@
       // If a type specifier follows, it will be diagnosed elsewhere.
       continue;
     }
+
+      // type-name
+    case tok::annot_template_id: {
+      TemplateIdAnnotation *TemplateId 
+        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+      if (TemplateId->Kind != TNK_Class_template) {
+        // This template-id does not refer to a type name, so we're
+        // done with the type-specifiers.
+        goto DoneWithDeclSpec;
+      }
+
+      // Turn the template-id annotation token into a type annotation
+      // token, then try again to parse it as a type-specifier.
+      if (AnnotateTemplateIdTokenAsType())
+        DS.SetTypeSpecError();
+
+      continue;
+    }
+
     // GNU attributes support.
     case tok::kw___attribute:
       DS.AddAttributes(ParseAttributes());
@@ -1749,7 +1755,7 @@
 ///         operator-function-id
 ///         conversion-function-id  [TODO]
 ///          '~' class-name         
-///         template-id             [TODO]
+///         template-id
 ///
 void Parser::ParseDirectDeclarator(Declarator &D) {
   DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
@@ -1768,21 +1774,9 @@
       if (Tok.is(tok::identifier)) {
         assert(Tok.getIdentifierInfo() && "Not an identifier?");
 
-        // If this identifier is followed by a '<', we may have a template-id.
-        DeclTy *Template;
-        Action::TemplateNameKind TNK;
-        if (getLang().CPlusPlus && NextToken().is(tok::less) &&
-            (TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), 
-                                          CurScope, Template))) {
-          IdentifierInfo *II = Tok.getIdentifierInfo();
-          AnnotateTemplateIdToken(Template, TNK, 0);
-          // FIXME: Set the declarator to a template-id. How? I don't
-          // know... for now, just use the identifier.
-          D.SetIdentifier(II, Tok.getLocation());
-        }
         // If this identifier is the name of the current class, it's a
         // constructor name. 
-        else if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)){
+        if (Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)){
           D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
                                                Tok.getLocation(), CurScope),
                            Tok.getLocation());
@@ -1791,6 +1785,21 @@
           D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
         ConsumeToken();
         goto PastIdentifier;
+      } else if (Tok.is(tok::annot_template_id)) {
+        TemplateIdAnnotation *TemplateId 
+          = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+
+        // FIXME: Could this template-id name a constructor?
+
+        // FIXME: This is an egregious hack, where we silently ignore
+        // the specialization (which should be a function template
+        // specialization name) and use the name instead. This hack
+        // will go away when we have support for function
+        // specializations.
+        D.SetIdentifier(TemplateId->Name, Tok.getLocation());
+        TemplateId->Destroy();
+        ConsumeToken();
+        goto PastIdentifier;
       } else if (Tok.is(tok::kw_operator)) {
         SourceLocation OperatorLoc = Tok.getLocation();
         SourceLocation EndLoc;
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, 
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index fb60bde..50e6657 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -42,6 +42,8 @@
     return true;
   }
 
+  bool HasScopeSpecifier = false;
+
   if (Tok.is(tok::coloncolon)) {
     // ::new and ::delete aren't nested-name-specifiers.
     tok::TokenKind NextKind = NextToken().getKind();
@@ -53,32 +55,132 @@
     SS.setBeginLoc(CCLoc);
     SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
     SS.setEndLoc(CCLoc);
-  } else if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
-    SS.setBeginLoc(Tok.getLocation());
-  } else {
-    // Not a CXXScopeSpecifier.
-    return false;
+    HasScopeSpecifier = true;
   }
 
-  // nested-name-specifier:
-  //   type-name '::'
-  //   namespace-name '::'
-  //   nested-name-specifier identifier '::'
-  //   nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
-  while (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
-    IdentifierInfo *II = Tok.getIdentifierInfo();
-    SourceLocation IdLoc = ConsumeToken();
-    assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
-    SourceLocation CCLoc = ConsumeToken();
-    if (SS.isInvalid())
+  while (true) {
+    // nested-name-specifier:
+    //   type-name '::'
+    //   namespace-name '::'
+    //   nested-name-specifier identifier '::'
+    if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) {
+      // We have an identifier followed by a '::'. Lookup this name
+      // as the name in a nested-name-specifier.
+      IdentifierInfo *II = Tok.getIdentifierInfo();
+      SourceLocation IdLoc = ConsumeToken();
+      assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+      SourceLocation CCLoc = ConsumeToken();
+      
+      if (!HasScopeSpecifier) {
+        SS.setBeginLoc(IdLoc);
+        HasScopeSpecifier = true;
+      }
+      
+      if (SS.isInvalid())
+        continue;
+      
+      SS.setScopeRep(
+        Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
+      SS.setEndLoc(CCLoc);
       continue;
+    }
 
-    SS.setScopeRep(
-         Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II));
-    SS.setEndLoc(CCLoc);
+    // nested-name-specifier:
+    //   type-name '::'
+    //   nested-name-specifier 'template'[opt] simple-template-id '::'
+    if ((Tok.is(tok::identifier) && NextToken().is(tok::less)) ||
+        Tok.is(tok::kw_template)) {
+      // Parse the optional 'template' keyword, then make sure we have
+      // 'identifier <' after it.
+      SourceLocation TemplateKWLoc;
+      if (Tok.is(tok::kw_template)) {
+        TemplateKWLoc = ConsumeToken();
+        
+        if (Tok.isNot(tok::identifier)) {
+          Diag(Tok.getLocation(), 
+               diag::err_id_after_template_in_nested_name_spec)
+            << SourceRange(TemplateKWLoc);
+          break;
+        }
+
+        if (NextToken().isNot(tok::less)) {
+          Diag(NextToken().getLocation(),
+               diag::err_less_after_template_name_in_nested_name_spec)
+            << Tok.getIdentifierInfo()->getName()
+            << SourceRange(TemplateKWLoc, Tok.getLocation());
+          break;
+        }
+      }
+      else {
+        // FIXME: If the nested-name-specifier thus far is dependent,
+        // we need to break out of here, because this '<' is taken as
+        // an operator and not as part of a simple-template-id.
+      }
+
+      DeclTy *Template = 0;
+      TemplateNameKind TNK = TNK_Non_template;
+      // FIXME: If the nested-name-specifier thus far is dependent,
+      // set TNK = TNK_Dependent_template_name and skip the
+      // "isTemplateName" check.
+      TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(),
+                                   CurScope, Template, &SS);
+      if (TNK) {
+        // We have found a template name, so annotate this this token
+        // with a template-id annotation. We do not permit the
+        // template-id to be translated into a type annotation,
+        // because some clients (e.g., the parsing of class template
+        // specializations) still want to see the original template-id
+        // token.
+        AnnotateTemplateIdToken(Template, TNK, &SS, TemplateKWLoc, false);
+        continue;
+      }
+    }
+
+    if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
+      // We have 
+      //
+      //   simple-template-id '::'
+      //
+      // So we need to check whether the simple-template-id is of the
+      // right kind (it should name a type), and then convert it into
+      // a type within the nested-name-specifier.
+      TemplateIdAnnotation *TemplateId 
+        = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+
+      if (TemplateId->Kind == TNK_Class_template) {
+        if (AnnotateTemplateIdTokenAsType(&SS))
+          SS.setScopeRep(0);
+
+        assert(Tok.is(tok::annot_typename) && 
+               "AnnotateTemplateIdTokenAsType isn't working");
+
+        Token TypeToken = Tok;
+        ConsumeToken();
+        assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
+        SourceLocation CCLoc = ConsumeToken();
+        
+        if (!HasScopeSpecifier) {
+          SS.setBeginLoc(TypeToken.getLocation());
+          HasScopeSpecifier = true;
+        }
+
+        SS.setScopeRep(
+          Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, 
+                                              TypeToken.getAnnotationValue(),
+                                              TypeToken.getAnnotationRange(),
+                                              CCLoc));
+        SS.setEndLoc(CCLoc);
+        continue;
+      } else
+        assert(false && "FIXME: Only class template names supported here");
+    }
+
+    // We don't have any tokens that form the beginning of a
+    // nested-name-specifier, so we're done.
+    break;
   }
-
-  return true;
+    
+  return HasScopeSpecifier;
 }
 
 /// ParseCXXIdExpression - Handle id-expression.
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 747a4de..64fc8fd 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -444,16 +444,49 @@
   return false;
 }
                                               
-/// AnnotateTemplateIdToken - The current token is an identifier that
-/// refers to the template declaration Template, and is followed by a
-/// '<'. Turn this template-id into a template-id annotation token.
+/// \brief Replace the tokens that form a simple-template-id with an
+/// annotation token containing the complete template-id.
+///
+/// The first token in the stream must be the name of a template that
+/// is followed by a '<'. This routine will parse the complete
+/// simple-template-id and replace the tokens with a single annotation
+/// token with one of two different kinds: if the template-id names a
+/// type (and \p AllowTypeAnnotation is true), the annotation token is
+/// a type annotation that includes the optional nested-name-specifier
+/// (\p SS). Otherwise, the annotation token is a template-id
+/// annotation that does not include the optional
+/// nested-name-specifier.
+///
+/// \param Template  the declaration of the template named by the first
+/// token (an identifier), as returned from \c Action::isTemplateName().
+///
+/// \param TemplateNameKind the kind of template that \p Template
+/// refers to, as returned from \c Action::isTemplateName().
+///
+/// \param SS if non-NULL, the nested-name-specifier that precedes
+/// this template name.
+///
+/// \param TemplateKWLoc if valid, specifies that this template-id
+/// annotation was preceded by the 'template' keyword and gives the
+/// location of that keyword. If invalid (the default), then this
+/// template-id was not preceded by a 'template' keyword.
+///
+/// \param AllowTypeAnnotation if true (the default), then a
+/// simple-template-id that refers to a class template, template
+/// template parameter, or other template that produces a type will be
+/// replaced with a type annotation token. Otherwise, the
+/// simple-template-id is always replaced with a template-id
+/// annotation token.
 void Parser::AnnotateTemplateIdToken(DeclTy *Template, TemplateNameKind TNK,
-                                     const CXXScopeSpec *SS) {
+                                     const CXXScopeSpec *SS, 
+                                     SourceLocation TemplateKWLoc,
+                                     bool AllowTypeAnnotation) {
   assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
   assert(Template && Tok.is(tok::identifier) && NextToken().is(tok::less) &&
          "Parser isn't at the beginning of a template-id");
 
   // Consume the template-name.
+  IdentifierInfo *Name = Tok.getIdentifierInfo();
   SourceLocation TemplateNameLoc = ConsumeToken();
 
   // Parse the enclosed template argument list.
@@ -476,7 +509,7 @@
     return; 
 
   // Build the annotation token.
-  if (TNK == Action::TNK_Class_template) {
+  if (TNK == TNK_Class_template && AllowTypeAnnotation) {
     Action::TypeResult Type 
       = Actions.ActOnClassTemplateId(Template, TemplateNameLoc,
                                      LAngleLoc, TemplateArgsPtr,
@@ -487,34 +520,96 @@
 
     Tok.setKind(tok::annot_typename);
     Tok.setAnnotationValue(Type.get());
+    if (SS && SS->isNotEmpty())
+      Tok.setLocation(SS->getBeginLoc());
+    else if (TemplateKWLoc.isValid())
+      Tok.setLocation(TemplateKWLoc);
+    else 
+      Tok.setLocation(TemplateNameLoc);
   } else {
     // This is a function template. We'll be building a template-id
     // annotation token.
-    Tok.setKind(tok::annot_template_id);    
+    Tok.setKind(tok::annot_template_id);
     TemplateIdAnnotation *TemplateId 
-      = (TemplateIdAnnotation *)malloc(sizeof(TemplateIdAnnotation) + 
-                                       sizeof(void*) * TemplateArgs.size());
+      = TemplateIdAnnotation::Allocate(TemplateArgs.size());
     TemplateId->TemplateNameLoc = TemplateNameLoc;
+    TemplateId->Name = Name;
     TemplateId->Template = Template;
+    TemplateId->Kind = TNK;
     TemplateId->LAngleLoc = LAngleLoc;
-    TemplateId->NumArgs = TemplateArgs.size();
-    void **Args = (void**)(TemplateId + 1);
-    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
+    TemplateId->RAngleLoc = RAngleLoc;
+    void **Args = TemplateId->getTemplateArgs();
+    bool *ArgIsType = TemplateId->getTemplateArgIsType();
+    SourceLocation *ArgLocs = TemplateId->getTemplateArgLocations();
+    for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg) {
       Args[Arg] = TemplateArgs[Arg];
+      ArgIsType[Arg] = TemplateArgIsType[Arg];
+      ArgLocs[Arg] = TemplateArgLocations[Arg];
+    }
     Tok.setAnnotationValue(TemplateId);
+    if (TemplateKWLoc.isValid())
+      Tok.setLocation(TemplateKWLoc);
+    else
+      Tok.setLocation(TemplateNameLoc);
+
+    TemplateArgsPtr.release();
   }
 
   // Common fields for the annotation token
   Tok.setAnnotationEndLoc(RAngleLoc);
-  Tok.setLocation(TemplateNameLoc);
-  if (SS && SS->isNotEmpty())
-    Tok.setLocation(SS->getBeginLoc());
 
   // In case the tokens were cached, have Preprocessor replace them with the
   // annotation token.
   PP.AnnotateCachedTokens(Tok);
 }
 
+/// \brief Replaces a template-id annotation token with a type
+/// annotation token.
+///
+/// \returns true if there was an error, false otherwise.
+bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
+  assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
+
+  TemplateIdAnnotation *TemplateId 
+    = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+  assert(TemplateId->Kind == TNK_Class_template &&
+         "Only works for class templates");
+  
+  ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
+                                     TemplateId->getTemplateArgs(),
+                                     TemplateId->getTemplateArgIsType(),
+                                     TemplateId->NumArgs);
+
+  Action::TypeResult Type 
+    = Actions.ActOnClassTemplateId(TemplateId->Template, 
+                                   TemplateId->TemplateNameLoc,
+                                   TemplateId->LAngleLoc, 
+                                   TemplateArgsPtr,
+                                   TemplateId->getTemplateArgLocations(),
+                                   TemplateId->RAngleLoc, SS);
+  if (Type.isInvalid()) {
+    // FIXME: better recovery?
+    ConsumeToken();
+    TemplateId->Destroy();
+    return true;
+  }
+
+  // Create the new "type" annotation token.
+  Tok.setKind(tok::annot_typename);
+  Tok.setAnnotationValue(Type.get());
+  if (SS && SS->isNotEmpty()) // it was a C++ qualified type name.
+    Tok.setLocation(SS->getBeginLoc());
+
+  // We might be backtracking, in which case we need to replace the
+  // template-id annotation token with the type annotation within the
+  // set of cached tokens. That way, we won't try to form the same
+  // class template specialization again.
+  PP.ReplaceLastTokenWithAnnotation(Tok);
+  TemplateId->Destroy();
+
+  return false;
+}
+
 /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
 ///
 ///       template-argument: [C++ 14.2]
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 7b09d21..a3ed027 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -778,31 +778,41 @@
       // them with the annotation token.
       PP.AnnotateCachedTokens(Tok);
       return true;
-    } else if (!getLang().CPlusPlus) {
+    } 
+
+    if (!getLang().CPlusPlus) {
       // If we're in C, we can't have :: tokens at all (the lexer won't return
       // them).  If the identifier is not a type, then it can't be scope either,
       // just early exit. 
       return false;
     }
     
-    // If this is a template-id, annotate the template-id token.
+    // If this is a template-id, annotate with a template-id or type token.
     if (NextToken().is(tok::less)) {
       DeclTy *Template;
       if (TemplateNameKind TNK 
             = Actions.isTemplateName(*Tok.getIdentifierInfo(),
-                                     CurScope, Template, &SS)) {
+                                     CurScope, Template, &SS))
         AnnotateTemplateIdToken(Template, TNK, &SS);
-        return true;
-      }
     }
 
-    // We either have an identifier that is not a type name or we have
-    // just created a template-id that might be a type name. Both
-    // cases will be handled below.
+    // The current token, which is either an identifier or a
+    // template-id, is not part of the annotation. Fall through to
+    // push that token back into the stream and complete the C++ scope
+    // specifier annotation.
   }
 
-  // FIXME: check for a template-id token here, and look it up if it
-  // names a type.
+  if (Tok.is(tok::annot_template_id)) {
+    TemplateIdAnnotation *TemplateId 
+      = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+    if (TemplateId->Kind == TNK_Class_template) {
+      // A template-id that refers to a type was parsed into a
+      // template-id annotation in a context where we weren't allowed
+      // to produce a type annotation token. Update the template-id
+      // annotation token to a type annotation token now.
+      return !AnnotateTemplateIdTokenAsType(&SS);
+    }
+  }
 
   if (SS.isEmpty())
     return false;
@@ -825,8 +835,8 @@
 }
 
 /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
-/// annotates C++ scope specifiers.  This returns true if the token was
-/// annotated.
+/// annotates C++ scope specifiers and template-ids.  This returns
+/// true if the token was annotated.
 /// 
 /// Note that this routine emits an error if you call it with ::new or ::delete
 /// as the current tokens, so only call it in contexts where these are invalid.
@@ -838,7 +848,7 @@
 
   CXXScopeSpec SS;
   if (!ParseOptionalCXXScopeSpecifier(SS))
-    return false;
+    return Tok.is(tok::annot_template_id);
 
   // Push the current token back into the token stream (or revert it if it is
   // cached) and use an annotation scope token for current token.