Implicit instantiation for function template specializations.

For a FunctionDecl that has been instantiated due to template argument
deduction, we now store the primary template from which it was
instantiated and the deduced template arguments. From this
information, we can instantiate the body of the function template.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74232 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 44b6802..a01fbb1 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -5566,12 +5566,15 @@
     }
   }
   if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
-    // Implicit instantiation of function templates
+    // Implicit instantiation of function templates and member functions of 
+    // class templates.
     if (!Function->getBody(Context)) {
-      if (Function->getInstantiatedFromMemberFunction())
+      // FIXME: distinguish between implicit instantiations of function
+      // templates and explicit specializations (the latter don't get
+      // instantiated, naturally).
+      if (Function->getInstantiatedFromMemberFunction() ||
+          Function->getPrimaryTemplate())
         PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
-
-      // FIXME: check for function template specializations.
     }
     
     
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 1d7e03e..03466f0 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -870,6 +870,10 @@
   if (!Specialization || Trap.hasErrorOccurred())
     return TDK_SubstitutionFailure;
 
+  // Turn the specialization into an actual function template specialization.
+  Specialization->setFunctionTemplateSpecialization(Context,
+                                                    FunctionTemplate,
+                                                    Info.take());
   return TDK_Success;
 }
 
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 0f67748..5e4fde7 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -29,10 +29,18 @@
 /// instantiate the given declaration.
 const TemplateArgumentList &
 Sema::getTemplateInstantiationArgs(NamedDecl *D) {
+  // Template arguments for a class template specialization.
   if (ClassTemplateSpecializationDecl *Spec 
         = dyn_cast<ClassTemplateSpecializationDecl>(D))
     return Spec->getTemplateArgs();
 
+  // Template arguments for a function template specialization.
+  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+    if (const TemplateArgumentList *TemplateArgs
+          = Function->getTemplateSpecializationArgs())
+      return *TemplateArgs;
+      
+  // Template arguments for a member of a class template specialization.
   DeclContext *EnclosingTemplateCtx = D->getDeclContext();
   while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) {
     assert(!EnclosingTemplateCtx->isFileContext() &&
@@ -158,8 +166,11 @@
           << Active->InstantiationRange;
       } else {
         FunctionDecl *Function = cast<FunctionDecl>(D);
-        unsigned DiagID = diag::note_template_member_function_here;
-        // FIXME: check for a function template
+        unsigned DiagID;
+        if (Function->getPrimaryTemplate())
+          DiagID = diag::note_function_template_spec_here;
+        else
+          DiagID = diag::note_template_member_function_here;
         Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), 
                      DiagID)
           << Function
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 95655d8..a05095f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -645,16 +645,17 @@
 /// function.
 void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                          FunctionDecl *Function) {
-  // FIXME: make this work for function template specializations, too.
-
   if (Function->isInvalidDecl())
     return;
 
   assert(!Function->getBody(Context) && "Already instantiated!");
   
   // Find the function body that we'll be substituting.
-  const FunctionDecl *PatternDecl 
-    = Function->getInstantiatedFromMemberFunction();
+  const FunctionDecl *PatternDecl = 0;
+  if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate())
+    PatternDecl = Primary->getTemplatedDecl();
+  else 
+    PatternDecl = Function->getInstantiatedFromMemberFunction();
   Stmt *Pattern = 0;
   if (PatternDecl)
     Pattern = PatternDecl->getBody(Context, PatternDecl);