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