]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: CTAD for less-specialized alias template [PR102529]
authorJason Merrill <jason@redhat.com>
Thu, 9 Feb 2023 20:58:35 +0000 (12:58 -0800)
committerJason Merrill <jason@redhat.com>
Thu, 9 Mar 2023 15:25:46 +0000 (10:25 -0500)
The standard was unclear what happens with the transformation of a deduction
guide if the initial template argument deduction fails for a reason other
than not deducing all the arguments; my implementation assumed that the
right thing was to give up on the deduction guide.  But in consideration of
CWG2664 this week I realized that we get a better result by just continuing
with an empty set of deductions, so the alias deduction guide is the same as
the original deduction guide plus the deducible constraint.

DR 2664
PR c++/102529

gcc/cp/ChangeLog:

* pt.cc (alias_ctad_tweaks): Continue after deduction failure.

gcc/testsuite/ChangeLog:

* g++.dg/DRs/dr2664.C: New test.
* g++.dg/cpp2a/class-deduction-alias15.C: New test.

gcc/cp/pt.cc
gcc/testsuite/g++.dg/DRs/dr2664.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/class-deduction-alias15.C [new file with mode: 0644]

index 8c73ea5b0fa5fcd8642888d000a01296a01ace6e..65341c40f97036a034ead6a6b3aba949ed554b4c 100644 (file)
@@ -30072,7 +30072,9 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
          tree targs = make_tree_vec (len);
          int err = unify (ftparms, targs, ret, utype, UNIFY_ALLOW_NONE, false);
          if (err)
-           continue;
+           /* CWG2664: Discard any deductions, still build the guide.  */
+           for (unsigned i = 0; i < len; ++i)
+             TREE_VEC_ELT (targs, i) = NULL_TREE;
 
          /* The number of parms for f' is the number of parms for A plus
             non-deduced parms of f.  */
diff --git a/gcc/testsuite/g++.dg/DRs/dr2664.C b/gcc/testsuite/g++.dg/DRs/dr2664.C
new file mode 100644 (file)
index 0000000..f6bf8e2
--- /dev/null
@@ -0,0 +1,17 @@
+// CWG 2664
+// { dg-do compile { target c++20 } }
+
+template <class S1, class S2> struct C {
+  C(...);
+};
+
+template<class T1> C(T1) -> C<T1, T1>;
+template<class T1, class T2> C(T1, T2) -> C<T1 *, T2>;
+
+template<class V1, class V2> using A = C<V1, V2>;
+
+C c1{""};
+A a1{""};
+
+C c2{"", 1};
+A a2{"", 1};
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias15.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias15.C
new file mode 100644 (file)
index 0000000..db615fa
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/102529
+// { dg-do compile { target c++20 } }
+
+template <typename T>
+struct C {
+    template <typename U>
+    C(U);
+};
+
+template <typename U>
+C(U) -> C<U*>;
+
+template <typename T>
+    requires true
+using A = C<T>;
+
+C ok(1);   // ok, a is a C<int*>
+A bad(2);  // fails