Keep track of more information within the template instantiation stack, e.g.,
by distinguishing between substitution that occurs for template
argument deduction vs. explicitly-specifiad template arguments. This
is used both to improve diagnostics and to make sure we only provide
SFINAE in those cases where SFINAE should apply.

In addition, deal with the sticky issue where SFINAE only considers
substitution of template arguments into the *type* of a function
template; we need to issue hard errors beyond this point, as
test/SemaTemplate/operator-template.cpp illustrates.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74651 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 3bc1cf9..6c2dc77 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -100,6 +100,30 @@
 
 Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, 
                                          SourceLocation PointOfInstantiation,
+                                      FunctionTemplateDecl *FunctionTemplate,
+                                        const TemplateArgument *TemplateArgs,
+                                                   unsigned NumTemplateArgs,
+                         ActiveTemplateInstantiation::InstantiationKind Kind,
+                                              SourceRange InstantiationRange)
+: SemaRef(SemaRef) {
+  
+  Invalid = CheckInstantiationDepth(PointOfInstantiation,
+                                    InstantiationRange);
+  if (!Invalid) {
+    ActiveTemplateInstantiation Inst;
+    Inst.Kind = Kind;
+    Inst.PointOfInstantiation = PointOfInstantiation;
+    Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate);
+    Inst.TemplateArgs = TemplateArgs;
+    Inst.NumTemplateArgs = NumTemplateArgs;
+    Inst.InstantiationRange = InstantiationRange;
+    SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+    Invalid = false;
+  }
+}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, 
+                                         SourceLocation PointOfInstantiation,
                           ClassTemplatePartialSpecializationDecl *PartialSpec,
                                          const TemplateArgument *TemplateArgs,
                                          unsigned NumTemplateArgs,
@@ -111,7 +135,7 @@
   if (!Invalid) {
     ActiveTemplateInstantiation Inst;
     Inst.Kind 
-      = ActiveTemplateInstantiation::PartialSpecDeductionInstantiation;
+      = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution;
     Inst.PointOfInstantiation = PointOfInstantiation;
     Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec);
     Inst.TemplateArgs = TemplateArgs;
@@ -148,6 +172,7 @@
 /// \brief Prints the current instantiation stack through a series of
 /// notes.
 void Sema::PrintInstantiationStack() {
+  // FIXME: In all of these cases, we need to show the template arguments
   for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator
          Active = ActiveTemplateInstantiations.rbegin(),
          ActiveEnd = ActiveTemplateInstantiations.rend();
@@ -183,7 +208,7 @@
       TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
       std::string TemplateArgsStr
         = TemplateSpecializationType::PrintTemplateArgumentList(
-                                                      Active->TemplateArgs, 
+                                                         Active->TemplateArgs, 
                                                       Active->NumTemplateArgs,
                                                       Context.PrintingPolicy);
       Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
@@ -193,18 +218,31 @@
       break;
     }
 
-    case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: {
-      ClassTemplatePartialSpecializationDecl *PartialSpec
-        = cast<ClassTemplatePartialSpecializationDecl>((Decl *)Active->Entity);
-      // FIXME: The active template instantiation's template arguments
-      // are interesting, too. We should add something like [with T =
-      // foo, U = bar, etc.] to the string.
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: {
+      FunctionTemplateDecl *FnTmpl 
+        = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
       Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
-                   diag::note_partial_spec_deduct_instantiation_here)
-        << Context.getTypeDeclType(PartialSpec)
-        << Active->InstantiationRange;
+                   diag::note_explicit_template_arg_substitution_here)
+        << FnTmpl << Active->InstantiationRange;
       break;
     }
+        
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      if (ClassTemplatePartialSpecializationDecl *PartialSpec
+            = dyn_cast<ClassTemplatePartialSpecializationDecl>(
+                                                    (Decl *)Active->Entity)) {
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     diag::note_partial_spec_deduct_instantiation_here)
+          << Context.getTypeDeclType(PartialSpec)
+          << Active->InstantiationRange;
+      } else {
+        FunctionTemplateDecl *FnTmpl
+          = cast<FunctionTemplateDecl>((Decl *)Active->Entity);
+        Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
+                     diag::note_function_template_deduction_instantiation_here)
+          << FnTmpl << Active->InstantiationRange;
+      }
+      break;
 
     }
   }
@@ -219,19 +257,20 @@
        ++Active) {
 
     switch(Active->Kind) {
-    case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation:
-      // We're in a template argument deduction context, so SFINAE
-      // applies.
-      return true;
-
+    case ActiveTemplateInstantiation::TemplateInstantiation:
+      // This is a template instantiation, so there is no SFINAE.
+      return false;
+        
     case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation:
       // A default template argument instantiation may or may not be a
       // SFINAE context; look further up the stack.
       break;
-
-    case ActiveTemplateInstantiation::TemplateInstantiation:
-      // This is a template instantiation, so there is no SFINAE.
-      return false;
+        
+    case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution:
+    case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution:
+      // We're either substitution explicitly-specified template arguments
+      // or deduced template arguments, so SFINAE applies.
+      return true;
     }
   }