Parsing and AST representation for dependent template names that occur
within nested-name-specifiers, e.g., for the "apply" in

  typename MetaFun::template apply<T1, T2>::type

At present, we can't instantiate these nested-name-specifiers, so our
testing is sketchy.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68081 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index e99e96a..fcbf4ee 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -134,7 +134,7 @@
 }
 
 TemplateNameKind 
-MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
+MinimalAction::isTemplateName(const IdentifierInfo &II, Scope *S,
                               TemplateTy &TemplateDecl,
                               const CXXScopeSpec *SS) {
   return TNK_Non_template;
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index f80afe3..11658d4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -513,7 +513,7 @@
       Token Next = NextToken();
       if (Next.is(tok::annot_template_id) && 
           static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
-          ->Kind == TNK_Class_template) {
+            ->Kind == TNK_Type_template) {
         // We have a qualified template-id, e.g., N::A<int>
         CXXScopeSpec SS;
         ParseOptionalCXXScopeSpecifier(SS);
@@ -640,7 +640,7 @@
     case tok::annot_template_id: {
       TemplateIdAnnotation *TemplateId 
         = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-      if (TemplateId->Kind != TNK_Class_template) {
+      if (TemplateId->Kind != TNK_Type_template) {
         // This template-id does not refer to a type name, so we're
         // done with the type-specifiers.
         goto DoneWithDeclSpec;
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index fdfc731..663fea5 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -307,7 +307,7 @@
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId 
       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-    if (TemplateId->Kind == TNK_Class_template) {
+    if (TemplateId->Kind == TNK_Type_template) {
       if (AnnotateTemplateIdTokenAsType(SS))
         return 0;
 
@@ -419,7 +419,7 @@
     TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     NameLoc = ConsumeToken();
 
-    if (TemplateId->Kind != TNK_Class_template) {
+    if (TemplateId->Kind != TNK_Type_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 ';'.
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 4d419bb..2c6963a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -92,9 +92,8 @@
         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();
+        SourceLocation TemplateKWLoc = ConsumeToken();
         
         if (Tok.isNot(tok::identifier)) {
           Diag(Tok.getLocation(), 
@@ -110,20 +109,20 @@
             << 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.
+
+        TemplateTy Template 
+          = Actions.ActOnDependentTemplateName(TemplateKWLoc,
+                                               *Tok.getIdentifierInfo(),
+                                               Tok.getLocation(),
+                                               SS);
+        AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
+                                &SS, TemplateKWLoc, false);
+        continue;
       }
 
       TemplateTy Template;
-      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);
+      TemplateNameKind 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
@@ -131,7 +130,7 @@
         // 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);
+        AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false);
         continue;
       }
     }
@@ -142,12 +141,13 @@
       //   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.
+      // right kind (it should name a type or be dependent), 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 (TemplateId->Kind == TNK_Type_template || 
+          TemplateId->Kind == TNK_Dependent_template_name) {
         if (AnnotateTemplateIdTokenAsType(&SS))
           SS.clear();
 
@@ -172,7 +172,7 @@
         SS.setEndLoc(CCLoc);
         continue;
       } else
-        assert(false && "FIXME: Only class template names supported here");
+        assert(false && "FIXME: Only type template names supported here");
     }
 
     // We don't have any tokens that form the beginning of a
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 8eda694..45d148e 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -531,8 +531,7 @@
     return; 
 
   // Build the annotation token.
-  // FIXME: Not just for class templates!
-  if (TNK == TNK_Class_template && AllowTypeAnnotation) {
+  if (TNK == TNK_Type_template && AllowTypeAnnotation) {
     Action::TypeResult Type 
       = Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
                                     LAngleLoc, TemplateArgsPtr,
@@ -550,8 +549,8 @@
     else 
       Tok.setLocation(TemplateNameLoc);
   } else {
-    // This is a function template. We'll be building a template-id
-    // annotation token.
+    // Build a template-id annotation token that can be processed
+    // later.
     Tok.setKind(tok::annot_template_id);
     TemplateIdAnnotation *TemplateId 
       = TemplateIdAnnotation::Allocate(TemplateArgs.size());
@@ -595,8 +594,9 @@
 
   TemplateIdAnnotation *TemplateId 
     = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-  assert(TemplateId->Kind == TNK_Class_template &&
-         "Only works for class templates");
+  assert((TemplateId->Kind == TNK_Type_template ||
+          TemplateId->Kind == TNK_Dependent_template_name) &&
+         "Only works for type and dependent templates");
   
   ASTTemplateArgsPtr TemplateArgsPtr(Actions, 
                                      TemplateId->getTemplateArgs(),
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index a101aaa..56e217a 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -901,7 +901,7 @@
   if (Tok.is(tok::annot_template_id)) {
     TemplateIdAnnotation *TemplateId 
       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
-    if (TemplateId->Kind == TNK_Class_template) {
+    if (TemplateId->Kind == TNK_Type_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