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/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 769e0d2..f597199 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -628,6 +628,28 @@
                                                     FunctionDecl *Tmpl) {
   if (Tmpl->isDeleted())
     New->setDeleted();
+  
+  // If we are performing substituting explicitly-specified template arguments
+  // or deduced template arguments into a function template and we reach this
+  // point, we are now past the point where SFINAE applies and have committed
+  // to keeping the new function template specialization. We therefore 
+  // convert the active template instantiation for the function template 
+  // into a template instantiation for this specific function template
+  // specialization, which is not a SFINAE context, so that we diagnose any
+  // further errors in the declaration itself.
+  typedef Sema::ActiveTemplateInstantiation ActiveInstType;
+  ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back();
+  if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
+      ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) {
+    if (FunctionTemplateDecl *FunTmpl 
+          = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) {
+      assert(FunTmpl->getTemplatedDecl() == Tmpl && 
+             "Deduction from the wrong function template?");
+      ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
+      ActiveInst.Entity = reinterpret_cast<uintptr_t>(New);
+    }
+  }
+    
   return false;
 }