Implement template argument deduction when taking the address of a
function template. Most of the change here is in factoring out the
common bits used for template argument deduction from a function call
and when taking the address of a function template.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75044 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index e64080e..b7edc01 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3702,7 +3702,8 @@
   }
 
   // We only look at pointers or references to functions.
-  if (!FunctionType->isFunctionType()) 
+  FunctionType = Context.getCanonicalType(FunctionType.getUnqualifiedType());
+  if (!FunctionType->isFunctionType())
     return 0;
 
   // Find the actual overloaded function declaration.
@@ -3722,44 +3723,69 @@
   }
 
   // Try to dig out the overloaded function.
-  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr))
+  FunctionTemplateDecl *FunctionTemplate = 0;
+  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
     Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
+    FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
+  }
 
-  // If there's no overloaded function declaration, we're done.
-  if (!Ovl)
+  // If there's no overloaded function declaration or function template, 
+  // we're done.
+  if (!Ovl && !FunctionTemplate)
     return 0;
  
+  OverloadIterator Fun;
+  if (Ovl)
+    Fun = Ovl;
+  else
+    Fun = FunctionTemplate;
+  
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
-  // FIXME: When templates or using declarations come along, we'll actually
-  // have to deal with duplicates, partial ordering, etc. For now, we 
-  // can just do a simple search.
-  FunctionType = Context.getCanonicalType(FunctionType.getUnqualifiedType());
-  for (OverloadedFunctionDecl::function_iterator Fun = Ovl->function_begin();
-       Fun != Ovl->function_end(); ++Fun) {
+  // FIXME: We still need to cope with duplicates, partial ordering, etc.
+  for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
     // C++ [over.over]p3:
     //   Non-member functions and static member functions match
     //   targets of type "pointer-to-function" or "reference-to-function."
     //   Nonstatic member functions match targets of
     //   type "pointer-to-member-function."
     // Note that according to DR 247, the containing class does not matter.
+
+    if (FunctionTemplateDecl *FunctionTemplate 
+          = dyn_cast<FunctionTemplateDecl>(*Fun)) {
+      // C++ [temp.deduct.funcaddr]p1:
+      //   Template arguments can be deduced from the type specified when 
+      //   taking the address of an overloaded function (13.4). The function 
+      //   template’s function type and the specified type are used as the 
+      //   types of P and A, and the deduction is done as described in 
+      //   14.8.2.4.
+      FunctionDecl *Specialization = 0;
+      TemplateDeductionInfo Info(Context);
+      if (TemplateDeductionResult Result
+            = DeduceTemplateArguments(FunctionTemplate, /*FIXME*/false,
+                                      /*FIXME:*/0, /*FIXME:*/0,
+                                      FunctionType, Specialization, Info)) {
+        // FIXME: make a note of the failed deduction for diagnostics.
+        (void)Result;
+      } else {
+        assert(FunctionType 
+                 == Context.getCanonicalType(Specialization->getType()));
+        return Specialization;
+      }
+    }
+    
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun)) {
       // Skip non-static functions when converting to pointer, and static
       // when converting to member pointer.
       if (Method->isStatic() == IsMember)
         continue;
-    } else if (IsMember)
+    } else if (IsMember) // FIXME: member templates
       continue;
 
     if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
       if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
         return FunDecl;
-    } else {
-      unsigned DiagID 
-        = PP.getDiagnostics().getCustomDiagID(Diagnostic::Warning,
-                   "Clang does not yet support templated conversion functions");
-      Diag(From->getLocStart(), DiagID);
-    }
+    } 
   }
 
   return 0;
@@ -4614,8 +4640,9 @@
     FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
     E->setType(Context.getPointerType(UnOp->getSubExpr()->getType()));
   } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
-    assert(isa<OverloadedFunctionDecl>(DR->getDecl()) && 
-           "Expected overloaded function");
+    assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
+            isa<FunctionTemplateDecl>(DR->getDecl())) && 
+           "Expected overloaded function or function template");
     DR->setDecl(Fn);
     E->setType(Fn->getType());
   } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {