Implement transformation of template names within the generic tree
transform, then use the result for template instantiation. The generic
transformation fixes a few issues:

  - It copes better with template template parameters and member
  templates (when they're implemented). 
  - The logic used to replace template template parameters with their
  arguments is now centralized in TransformDecl, so that it will apply
  for other declaration-instantiation steps.
  - The error-recovery strategy is normalized now, so that any error
  results in a NULL TemplateName.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78292 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 70ad317..24deb4b 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -171,8 +171,10 @@
   
   /// \brief Transform the given template name.
   /// 
-  /// FIXME: At the moment, subclasses must override this.
-  TemplateName TransformTemplateName(TemplateName Template);
+  /// By default, transforms the template name by transforming the declarations
+  /// and nested-name-specifiers that occur within the template name. 
+  /// Subclasses may override this function to provide alternate behavior.
+  TemplateName TransformTemplateName(TemplateName Name);
   
   /// \brief Transform the given template argument.
   ///
@@ -433,6 +435,36 @@
                                                   SourceRange Range,
                                                   bool TemplateKW,
                                                   QualType T);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and the template
+  /// that the template name refers to.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   bool TemplateKW,
+                                   TemplateDecl *Template);
+
+  /// \brief Build a new template name given a nested name specifier, a flag
+  /// indicating whether the "template" keyword was provided, and a set of
+  /// overloaded function templates.
+  ///
+  /// By default, builds the new template name directly. Subclasses may override
+  /// this routine to provide different behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   bool TemplateKW,
+                                   OverloadedFunctionDecl *Ovl);
+  
+  /// \brief Build a new template name given a nested name specifier and the
+  /// name that is referred to as a template.
+  ///
+  /// By default, performs semantic analysis to determine whether the name can
+  /// be resolved to a specific template, then builds the appropriate kind of
+  /// template name. Subclasses may override this routine to provide different
+  /// behavior.
+  TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                   const IdentifierInfo &II);
 };
   
 template<typename Derived>
@@ -477,6 +509,9 @@
   case NestedNameSpecifier::TypeSpecWithTemplate:
   case NestedNameSpecifier::TypeSpec: {
     QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0));
+    if (T.isNull())
+      return 0;
+    
     if (!getDerived().AlwaysRebuild() &&
         Prefix == NNS->getPrefix() &&
         T == QualType(NNS->getAsType(), 0))
@@ -493,6 +528,88 @@
 }
 
 template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::TransformTemplateName(TemplateName Name) {
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
+    NestedNameSpecifier *NNS 
+      = getDerived().TransformNestedNameSpecifier(QTN->getQualifier(),
+                      /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS)
+      return TemplateName();
+    
+    if (TemplateDecl *Template = QTN->getTemplateDecl()) {
+      TemplateDecl *TransTemplate 
+        = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+      if (!TransTemplate)
+        return TemplateName();
+      
+      if (!getDerived().AlwaysRebuild() &&
+          NNS == QTN->getQualifier() &&
+          TransTemplate == Template)
+        return Name;
+      
+      return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+                                              TransTemplate);
+    }
+      
+    OverloadedFunctionDecl *Ovl = QTN->getOverloadedFunctionDecl();
+    assert(Ovl && "Not a template name or an overload set?");
+    OverloadedFunctionDecl *TransOvl 
+      = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+    if (!TransOvl)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == QTN->getQualifier() &&
+        TransOvl == Ovl)
+      return Name;
+    
+    return getDerived().RebuildTemplateName(NNS, QTN->hasTemplateKeyword(),
+                                            TransOvl);
+  }
+  
+  if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
+    NestedNameSpecifier *NNS 
+      = getDerived().TransformNestedNameSpecifier(DTN->getQualifier(),
+                        /*FIXME:*/SourceRange(getDerived().getBaseLocation()));
+    if (!NNS)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        NNS == DTN->getQualifier())
+      return Name;
+    
+    return getDerived().RebuildTemplateName(NNS, *DTN->getName());
+  }
+  
+  if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
+    TemplateDecl *TransTemplate 
+      = cast_or_null<TemplateDecl>(getDerived().TransformDecl(Template));
+    if (!TransTemplate)
+      return TemplateName();
+    
+    if (!getDerived().AlwaysRebuild() &&
+        TransTemplate == Template)
+      return Name;
+    
+    return TemplateName(TransTemplate);
+  }
+  
+  OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl();
+  assert(Ovl && "Not a template name or an overload set?");
+  OverloadedFunctionDecl *TransOvl 
+    = cast_or_null<OverloadedFunctionDecl>(getDerived().TransformDecl(Ovl));
+  if (!TransOvl)
+    return TemplateName();
+  
+  if (!getDerived().AlwaysRebuild() &&
+      TransOvl == Ovl)
+    return Name;
+  
+  return TemplateName(TransOvl);
+}
+
+template<typename Derived>
 TemplateArgument 
 TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
   switch (Arg.getKind()) {
@@ -1343,6 +1460,51 @@
   return 0;
 }
   
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            bool TemplateKW,
+                                            TemplateDecl *Template) {
+  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, 
+                                                  Template);
+}
+
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            bool TemplateKW,
+                                            OverloadedFunctionDecl *Ovl) {
+  return SemaRef.Context.getQualifiedTemplateName(Qualifier, TemplateKW, Ovl);
+}
+
+template<typename Derived>
+TemplateName 
+TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier,
+                                            const IdentifierInfo &II) {
+  if (Qualifier->isDependent())
+    return SemaRef.Context.getDependentTemplateName(Qualifier, &II);
+  
+  // Somewhat redundant with ActOnDependentTemplateName.
+  CXXScopeSpec SS;
+  SS.setRange(SourceRange(getDerived().getBaseLocation()));
+  SS.setScopeRep(Qualifier);
+  Sema::TemplateTy Template;
+  TemplateNameKind TNK = SemaRef.isTemplateName(II, 0, Template, &SS);
+  if (TNK == TNK_Non_template) {
+    SemaRef.Diag(getDerived().getBaseLocation(), 
+                 diag::err_template_kw_refers_to_non_template)
+      << &II;
+    return TemplateName();
+  } else if (TNK == TNK_Function_template) {
+    SemaRef.Diag(getDerived().getBaseLocation(), 
+                 diag::err_template_kw_refers_to_non_template)
+      << &II;
+    return TemplateName();
+  }
+  
+  return Template.getAsVal<TemplateName>();  
+}
+  
 } // end namespace clang
 
 #endif // LLVM_CLANG_SEMA_TREETRANSFORM_H