Fix multilevel deduction where an outer pack is used in the type of an
authorRichard Smith <richard@metafoo.co.uk>
Mon, 22 Jun 2020 23:45:12 +0000 (16:45 -0700)
committerRichard Smith <richard@metafoo.co.uk>
Mon, 22 Jun 2020 23:47:51 +0000 (16:47 -0700)
inner non-type pack at a different index.

We previously considered the index of the outer pack (which would refer
to an unrelated template parameter) to be deduced by deducing the inner
pack, because we inspected the (largely meaningless) type of an expanded
non-type template parameter pack.

clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/SemaTemplate/deduction-guide.cpp

index 877020e..e6569d4 100644 (file)
@@ -738,8 +738,9 @@ private:
       // 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());
+        if (!NTTP->isExpandedParameterPack())
+          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.
index c1ce625..3ac37ac 100644 (file)
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 -std=c++2a -verify -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s
+// expected-no-diagnostics
 
 template<auto ...> struct X {};
 
-template<typename T, typename ...Ts> struct A { // expected-note 2{{candidate}}
-  template<Ts ...Ns, T *...Ps> A(X<Ps...>, Ts (*...qs)[Ns]); // expected-note {{candidate}}
+template<typename T, typename ...Ts> struct A {
+  template<Ts ...Ns, T *...Ps> A(X<Ps...>, Ts (*...qs)[Ns]);
 };
 int arr1[3], arr2[3];
 short arr3[4];
-// FIXME: The CTAD deduction here succeeds, but the initialization deduction spuriously fails.
-A a(X<&arr1, &arr2>{}, &arr1, &arr2, &arr3); // FIXME: expected-error {{no matching constructor}}
+A a(X<&arr1, &arr2>{}, &arr1, &arr2, &arr3);
 using AT = decltype(a);
 using AT = A<int[3], int, int, short>;