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/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 9f2be1c..5f16ef3 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -939,18 +939,35 @@
           Ctx = Method->getParent();
           MemberType = Method->getType();
         }
+      } else if (FunctionTemplateDecl *FunTmpl 
+                   = dyn_cast<FunctionTemplateDecl>(D)) {
+        if (CXXMethodDecl *Method 
+              = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())) {
+          if (!Method->isStatic()) {          
+            Ctx = Method->getParent();
+            MemberType = Context.OverloadTy;
+          }
+        }
       } else if (OverloadedFunctionDecl *Ovl 
                    = dyn_cast<OverloadedFunctionDecl>(D)) {
+        // FIXME: We need an abstraction for iterating over one or more function
+        // templates or functions. This code is far too repetitive!
         for (OverloadedFunctionDecl::function_iterator 
                Func = Ovl->function_begin(),
                FuncEnd = Ovl->function_end();
              Func != FuncEnd; ++Func) {
-          if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(*Func))
-            if (!DMethod->isStatic()) {
-              Ctx = Ovl->getDeclContext();
-              MemberType = Context.OverloadTy;
-              break;
-            }
+          CXXMethodDecl *DMethod = 0;
+          if (FunctionTemplateDecl *FunTmpl 
+                = dyn_cast<FunctionTemplateDecl>(*Func))
+            DMethod = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+          else
+            DMethod = dyn_cast<CXXMethodDecl>(*Func);
+
+          if (DMethod && !DMethod->isStatic()) {
+            Ctx = DMethod->getDeclContext();
+            MemberType = Context.OverloadTy;
+            break;
+          }
         }
       }
 
@@ -2112,6 +2129,13 @@
                                             MemberFn, MemberLoc,
                                             MemberFn->getType()));
     }
+    if (FunctionTemplateDecl *FunTmpl 
+          = dyn_cast<FunctionTemplateDecl>(MemberDecl)) {
+      MarkDeclarationReferenced(MemberLoc, MemberDecl);
+      return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
+                                            FunTmpl, MemberLoc,
+                                            Context.OverloadTy));
+    }
     if (OverloadedFunctionDecl *Ovl
           = dyn_cast<OverloadedFunctionDecl>(MemberDecl))
       return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl,