diff options
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 48 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp | 17 |
2 files changed, 46 insertions, 19 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 1d43b3fd4d..9970005b69 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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); diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp index 16b5cd297d..8b18189bb3 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p6.cpp @@ -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); + } +} |