]> granicus.if.org Git - clang/commitdiff
C++11 [temp.deduct.call]p6 tweak: when given a set of overlaoded
authorDouglas Gregor <dgregor@apple.com>
Mon, 12 Mar 2012 21:09:16 +0000 (21:09 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 12 Mar 2012 21:09:16 +0000 (21:09 +0000)
functions that includes an explicit template argument list, perform
an inner deduction against each of the function templates in that list
and, if successful, use the result of that deduction for the outer
template argument deduction. Fixes PR11713.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152575 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp

index 1d43b3fd4d52984c3e7609881c264227eea8169f..9970005b691e94e01e74d685aedb4bbc116ad7a3 100644 (file)
@@ -2709,36 +2709,48 @@ ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams,
   if (R.IsAddressOfOperand)
     TDF |= TDF_IgnoreQualifiers;
 
-  // If there were explicit template arguments, we can only find
-  // something via C++ [temp.arg.explicit]p3, i.e. if the arguments
-  // unambiguously name a full specialization.
-  if (Ovl->hasExplicitTemplateArgs()) {
-    // But we can still look for an explicit specialization.
-    if (FunctionDecl *ExplicitSpec
-          = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
-      return GetTypeOfFunction(S.Context, R, ExplicitSpec);
-    return QualType();
-  }
-
   // C++0x [temp.deduct.call]p6:
   //   When P is a function type, pointer to function type, or pointer
   //   to member function type:
 
   if (!ParamType->isFunctionType() &&
       !ParamType->isFunctionPointerType() &&
-      !ParamType->isMemberFunctionPointerType())
-    return QualType();
+      !ParamType->isMemberFunctionPointerType()) {
+    if (Ovl->hasExplicitTemplateArgs()) {
+      // But we can still look for an explicit specialization.
+      if (FunctionDecl *ExplicitSpec
+            = S.ResolveSingleFunctionTemplateSpecialization(Ovl))
+        return GetTypeOfFunction(S.Context, R, ExplicitSpec);
+    }
 
+    return QualType();
+  }
+  
+  // Gather the explicit template arguments, if any.
+  TemplateArgumentListInfo ExplicitTemplateArgs;
+  if (Ovl->hasExplicitTemplateArgs())
+    Ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
   QualType Match;
   for (UnresolvedSetIterator I = Ovl->decls_begin(),
          E = Ovl->decls_end(); I != E; ++I) {
     NamedDecl *D = (*I)->getUnderlyingDecl();
 
-    //   - If the argument is an overload set containing one or more
-    //     function templates, the parameter is treated as a
-    //     non-deduced context.
-    if (isa<FunctionTemplateDecl>(D))
-      return QualType();
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
+      //   - If the argument is an overload set containing one or more
+      //     function templates, the parameter is treated as a
+      //     non-deduced context.
+      if (!Ovl->hasExplicitTemplateArgs())
+        return QualType();
+      
+      // Otherwise, see if we can resolve a function type 
+      FunctionDecl *Specialization = 0;
+      TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc());
+      if (S.DeduceTemplateArguments(FunTmpl, &ExplicitTemplateArgs,
+                                    Specialization, Info))
+        continue;
+      
+      D = Specialization;
+    }
 
     FunctionDecl *Fn = cast<FunctionDecl>(D);
     QualType ArgType = GetTypeOfFunction(S.Context, R, Fn);
index 16b5cd297d8bbb222d1b7644062521cc28ee2807..8b18189bb3da6a0c6f2e55ac317181d7bd0c218e 100644 (file)
@@ -50,7 +50,7 @@ namespace test0 {
 
 namespace test1 {
   template<class T> void invoke(void (*f)(T)) { f(T()); } // expected-note 6 {{couldn't infer template argument}} \
-  // expected-note {{failed template argument deduction}}
+  // expected-note {{candidate template ignored: couldn't infer template argument 'T'}}
 
   template<class T> void temp(T);
   void test0() {
@@ -111,3 +111,18 @@ namespace rdar8360106 {
     f2(&g, 1);
   }
 }
+
+namespace PR11713 {
+  template<typename T>
+  int f(int, int, int);
+
+  template<typename T>
+  float f(float, float);
+
+  template<typename R, typename B1, typename B2, typename A1, typename A2>
+  R& g(R (*)(B1, B2), A1, A2);
+
+  void h() {
+    float &fr = g(f<int>, 1, 2);
+  }
+}