[clang] e8f198d - Fix pack deduction to only deduce the arity of packs that are actually
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 17 00:55:05 PST 2020
Cherry-picked in e241c8fe6d2e6d83e9fb32bd34da8ffcdc0dd83d. Thanks!
On Thu, Jan 16, 2020 at 1:22 AM Richard Smith <richard at metafoo.co.uk> wrote:
>
> Hi Hans,
>
> Please consider this bugfix for the Clang 10 release branch.
>
> On Wed, 15 Jan 2020 at 16:21, Richard Smith via cfe-commits <cfe-commits at lists.llvm.org> wrote:
>>
>>
>> Author: Richard Smith
>> Date: 2020-01-15T16:21:08-08:00
>> New Revision: e8f198dd9e9dabed8d50276465906e7c8827cada
>>
>> URL: https://github.com/llvm/llvm-project/commit/e8f198dd9e9dabed8d50276465906e7c8827cada
>> DIFF: https://github.com/llvm/llvm-project/commit/e8f198dd9e9dabed8d50276465906e7c8827cada.diff
>>
>> LOG: Fix pack deduction to only deduce the arity of packs that are actually
>> expanded by the deduced pack.
>>
>> We recently started also deducing the arity of separately-expanded packs
>> that are merely mentioned within the pack in question, which is
>> incorrect.
>>
>> Added:
>>
>>
>> Modified:
>> clang/lib/Sema/SemaTemplateDeduction.cpp
>> clang/test/SemaTemplate/deduction.cpp
>>
>> Removed:
>>
>>
>>
>> ################################################################################
>> diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
>> index 1b9f1b2144d1..048a50a741e4 100644
>> --- a/clang/lib/Sema/SemaTemplateDeduction.cpp
>> +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
>> @@ -724,38 +724,48 @@ class PackDeductionScope {
>> // Compute the set of template parameter indices that correspond to
>> // parameter packs expanded by the pack expansion.
>> llvm::SmallBitVector SawIndices(TemplateParams->size());
>> + llvm::SmallVector<TemplateArgument, 4> ExtraDeductions;
>>
>> auto AddPack = [&](unsigned Index) {
>> if (SawIndices[Index])
>> return;
>> SawIndices[Index] = true;
>> addPack(Index);
>> +
>> + // Deducing a parameter pack that is a pack expansion also constrains the
>> + // packs appearing in that parameter to have the same deduced arity. Also,
>> + // in C++17 onwards, deducing a non-type template parameter deduces its
>> + // type, so we need to collect the pending deduced values for those packs.
>> + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(
>> + TemplateParams->getParam(Index))) {
>> + if (auto *Expansion = dyn_cast<PackExpansionType>(NTTP->getType()))
>> + ExtraDeductions.push_back(Expansion->getPattern());
>> + }
>> + // FIXME: Also collect the unexpanded packs in any type and template
>> + // parameter packs that are pack expansions.
>> };
>>
>> - // First look for unexpanded packs in the pattern.
>> - SmallVector<UnexpandedParameterPack, 2> Unexpanded;
>> - S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
>> - for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
>> - unsigned Depth, Index;
>> - std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
>> - if (Depth == Info.getDeducedDepth())
>> - AddPack(Index);
>> - }
>> + auto Collect = [&](TemplateArgument Pattern) {
>> + SmallVector<UnexpandedParameterPack, 2> Unexpanded;
>> + S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
>> + for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
>> + unsigned Depth, Index;
>> + std::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
>> + if (Depth == Info.getDeducedDepth())
>> + AddPack(Index);
>> + }
>> + };
>> +
>> + // Look for unexpanded packs in the pattern.
>> + Collect(Pattern);
>> assert(!Packs.empty() && "Pack expansion without unexpanded packs?");
>>
>> unsigned NumNamedPacks = Packs.size();
>>
>> - // We can also have deduced template parameters that do not actually
>> - // appear in the pattern, but can be deduced by it (the type of a non-type
>> - // template parameter pack, in particular). These won't have prevented us
>> - // from partially expanding the pack.
>> - llvm::SmallBitVector Used(TemplateParams->size());
>> - MarkUsedTemplateParameters(S.Context, Pattern, /*OnlyDeduced*/true,
>> - Info.getDeducedDepth(), Used);
>> - for (int Index = Used.find_first(); Index != -1;
>> - Index = Used.find_next(Index))
>> - if (TemplateParams->getParam(Index)->isParameterPack())
>> - AddPack(Index);
>> + // Also look for unexpanded packs that are indirectly deduced by deducing
>> + // the sizes of the packs in this pattern.
>> + while (!ExtraDeductions.empty())
>> + Collect(ExtraDeductions.pop_back_val());
>>
>> return NumNamedPacks;
>> }
>>
>> diff --git a/clang/test/SemaTemplate/deduction.cpp b/clang/test/SemaTemplate/deduction.cpp
>> index 1f1c30a8b4ab..7268912dd6c5 100644
>> --- a/clang/test/SemaTemplate/deduction.cpp
>> +++ b/clang/test/SemaTemplate/deduction.cpp
>> @@ -546,3 +546,21 @@ namespace designators {
>>
>> static_assert(f({.a = 1, .b = 2}) == 3, ""); // expected-error {{no matching function}}
>> }
>> +
>> +namespace nested_packs {
>> + template<typename ...T, typename ...U> void f(T (*...f)(U...)); // expected-note {{deduced packs of
>> diff erent lengths for parameter 'U' (<> vs. <int>)}}
>> + void g() { f(g); f(g, g); f(g, g, g); }
>> + void h(int) { f(h); f(h, h); f(h, h, h); }
>> + void i() { f(g, h); } // expected-error {{no matching function}}
>> +
>> +#if __cplusplus >= 201703L
>> + template<auto ...A> struct Q {};
>> + template<typename ...T, T ...A, T ...B> void q(Q<A...>, Q<B...>); // #q
>> + void qt(Q<> q0, Q<1, 2> qii, Q<1, 2, 3> qiii) {
>> + q(q0, q0);
>> + q(qii, qii);
>> + q(qii, qiii); // expected-error {{no match}} expected-note@#q {{deduced packs of
>> diff erent lengths for parameter 'T' (<int, int> vs. <int, int, int>)}}
>> + q(q0, qiii); // expected-error {{no match}} expected-note@#q {{deduced packs of
>> diff erent lengths for parameter 'T' (<> vs. <int, int, int>)}}
>> + }
>> +#endif
>> +}
>>
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list