Implement support for calling member function templates, which involves:
  - Allowing one to name a member function template within a class
  template and on the right-hand side of a member access expression.
  - Template argument deduction for calls to member function templates.
  - Registering specializations of member function templates (and
  finding them later).



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79581 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 23256a8..8d75ac4 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -457,7 +457,26 @@
 }
 
 Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
-  // FIXME: Look for existing, explicit specializations.
+  // Check whether there is already a function template specialization for
+  // this declaration.
+  FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
+  void *InsertPos = 0;
+  if (FunctionTemplate) {
+    llvm::FoldingSetNodeID ID;
+    FunctionTemplateSpecializationInfo::Profile(ID, 
+                                          TemplateArgs.getFlatArgumentList(),
+                                                TemplateArgs.flat_size(),
+                                                SemaRef.Context);
+    
+    FunctionTemplateSpecializationInfo *Info 
+      = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, 
+                                                                   InsertPos);
+    
+    // If we already have a function template specialization, return it.
+    if (Info)
+      return Info->Function;
+  }
+
   Sema::LocalInstantiationScope Scope(SemaRef);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -471,7 +490,9 @@
     = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), 
                             D->getDeclName(), T, D->getDeclaratorInfo(),
                             D->isStatic(), D->isInline());
-  Method->setInstantiationOfMemberFunction(D);
+
+  if (!FunctionTemplate)
+    Method->setInstantiationOfMemberFunction(D);
 
   // If we are instantiating a member function defined 
   // out-of-line, the instantiation will have the same lexical
@@ -501,8 +522,14 @@
   SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
 
-  if (!Method->isInvalidDecl() || !PrevDecl)
-    Owner->addDecl(Method);
+  if (FunctionTemplate)
+    // Record this function template specialization.
+    Method->setFunctionTemplateSpecialization(SemaRef.Context,
+                                              FunctionTemplate,
+                                              &TemplateArgs,
+                                              InsertPos);
+  else if (!Method->isInvalidDecl() || !PrevDecl)
+      Owner->addDecl(Method);
   return Method;
 }