From: Richard Smith Date: Thu, 5 Jan 2017 20:27:28 +0000 (+0000) Subject: If an explicitly-specified pack might have been extended by template argument X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c9f404a2528fa5953a556c5adfe1219f94653a9;p=clang If an explicitly-specified pack might have been extended by template argument deduction, don't forget to check the argument is valid. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291170 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 6c90b5c226..7750b9c0ea 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2215,25 +2215,26 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments( if (!Deduced[I].isNull()) { if (I < NumAlreadyConverted) { - // We have already fully type-checked and converted this - // argument, because it was explicitly-specified. Just record the - // presence of this argument. - Builder.push_back(Deduced[I]); // We may have had explicitly-specified template arguments for a // template parameter pack (that may or may not have been extended // via additional deduced arguments). - if (Param->isParameterPack() && CurrentInstantiationScope) { - if (CurrentInstantiationScope->getPartiallySubstitutedPack() == - Param) { - // Forget the partially-substituted pack; its substitution is now - // complete. - CurrentInstantiationScope->ResetPartiallySubstitutedPack(); - } + if (Param->isParameterPack() && CurrentInstantiationScope && + CurrentInstantiationScope->getPartiallySubstitutedPack() == Param) { + // Forget the partially-substituted pack; its substitution is now + // complete. + CurrentInstantiationScope->ResetPartiallySubstitutedPack(); + // We still need to check the argument in case it was extended by + // deduction. + } else { + // We have already fully type-checked and converted this + // argument, because it was explicitly-specified. Just record the + // presence of this argument. + Builder.push_back(Deduced[I]); + continue; } - continue; } - // We have deduced this argument, so it still needs to be + // We may have deduced this argument, so it still needs to be // checked and converted. if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info, IsDeduced, Builder)) { diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index 940f6018f2..2275a8b3b7 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -428,3 +428,17 @@ namespace deduction_from_empty_list { f<1>({0}, {0, 1}); // expected-error {{no matching}} } } + +namespace check_extended_pack { + template struct X { typedef int type; }; + template void f(typename X::type...); + template void f(T, int, int); + void g() { + f(0, 0, 0); + } + + template struct Y {}; + template void g(Y); // expected-note {{deduced non-type template argument does not have the same type as the corresponding template parameter ('int *' vs 'int')}} + int n; + void h() { g<0>(Y<0, &n>()); } // expected-error {{no matching function}} +}