From: Richard Smith Date: Fri, 2 Oct 2015 00:49:37 +0000 (+0000) Subject: PR24921: checking explicitly-specified template arguments when matching a X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2596889471d67ebd964a62bbd8f1422e882cf095;p=clang PR24921: checking explicitly-specified template arguments when matching a partial specialization can perform conversions on the argument. Be sure we start again from the original argument when checking each possible template. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249114 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 22625527f5..de89ce15ff 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3923,7 +3923,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // No problems found with the new argument list, propagate changes back // to caller. - TemplateArgs = NewArgs; + TemplateArgs = std::move(NewArgs); return false; } @@ -6756,6 +6756,9 @@ bool Sema::CheckFunctionTemplateSpecialization( UnresolvedSet<8> Candidates; TemplateSpecCandidateSet FailedCandidates(FD->getLocation()); + llvm::SmallDenseMap + ConvertedTemplateArgs; + DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { @@ -6785,6 +6788,10 @@ bool Sema::CheckFunctionTemplateSpecialization( } } + TemplateArgumentListInfo Args; + if (ExplicitTemplateArgs) + Args = *ExplicitTemplateArgs; + // C++ [temp.expl.spec]p11: // A trailing template-argument can be left unspecified in the // template-id naming an explicit function template specialization @@ -6796,7 +6803,7 @@ bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( cast(FunTmpl->getFirstDecl()), - ExplicitTemplateArgs, FT, Specialization, Info)) { + ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) { // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. FailedCandidates.addCandidate() @@ -6807,6 +6814,8 @@ bool Sema::CheckFunctionTemplateSpecialization( } // Record this candidate. + if (ExplicitTemplateArgs) + ConvertedTemplateArgs[Specialization] = std::move(Args); Candidates.addDecl(Specialization, I.getAccess()); } } @@ -6885,10 +6894,10 @@ bool Sema::CheckFunctionTemplateSpecialization( // Take copies of (semantic and syntactic) template argument lists. const TemplateArgumentList* TemplArgs = new (Context) TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); - FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), - TemplArgs, /*InsertPos=*/nullptr, - SpecInfo->getTemplateSpecializationKind(), - ExplicitTemplateArgs); + FD->setFunctionTemplateSpecialization( + Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr, + SpecInfo->getTemplateSpecializationKind(), + ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr); // The "previous declaration" for this function template specialization is // the prior function template specialization. diff --git a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp index 5000927d89..548f7f8f34 100644 --- a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp +++ b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp @@ -148,3 +148,10 @@ namespace DeclMatch { template int f() { return X::n; } int k = f(); // ok, friend } + +namespace PR24921 { + enum E { e }; + template void f(); + template void f(int); + template<> void f() {} +}