[pushed] c++: alias ctad refinements [PR109321]
Checks
Commit Message
Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
The two hunks fix missing handling demonstrated by the two testcases: first,
if we omit one alias template parm but include another, we need to rewrite
the deduced template args to reflect the new position of the included parm.
Second, if we can't deduce any template args for a parameter pack, it is
deduced to an empty pack.
PR c++/109321
PR c++/109320
gcc/cp/ChangeLog:
* pt.cc (alias_ctad_tweaks): Rewrite deduced args.
(type_targs_deducible_from): Handle null pack deduction.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/class-deduction-alias16.C: New test.
* g++.dg/cpp2a/class-deduction-alias17.C: New test.
---
gcc/cp/pt.cc | 62 ++++++++++++++-----
.../g++.dg/cpp2a/class-deduction-alias16.C | 7 +++
.../g++.dg/cpp2a/class-deduction-alias17.C | 9 +++
3 files changed, 64 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias16.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias17.C
base-commit: b3c5933ee726004e4e47291d422dfe7ac3345062
@@ -30123,8 +30123,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
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. */
+ /* The number of parms for f' is the number of parms of A used in
+ the deduced arguments plus non-deduced parms of f. */
unsigned ndlen = 0;
unsigned j;
for (unsigned i = 0; i < len; ++i)
@@ -30142,22 +30142,34 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
TREE_VALUE (current_template_parms) = gtparms;
j = 0;
- /* First copy over the parms of A. */
+ unsigned level = 1;
+
+ /* First copy over the used parms of A. */
+ tree atargs = make_tree_vec (natparms);
for (unsigned i = 0; i < natparms; ++i)
{
tree elt = TREE_VEC_ELT (atparms, i);
if (ftpi.found (elt))
- TREE_VEC_ELT (gtparms, j++) = elt;
+ {
+ unsigned index = j++;
+ tree nelt = rewrite_tparm_list (elt, index, level,
+ atargs, i, complain);
+ TREE_VEC_ELT (gtparms, index) = nelt;
+ }
}
gcc_checking_assert (j == nusedatparms);
+ /* Adjust the deduced template args for f to refer to the A parms
+ with their new indexes. */
+ if (nusedatparms && nusedatparms != natparms)
+ targs = tsubst_template_args (targs, atargs, complain, in_decl);
+
/* Now rewrite the non-deduced parms of f. */
for (unsigned i = 0; ndlen && i < len; ++i)
if (TREE_VEC_ELT (targs, i) == NULL_TREE)
{
--ndlen;
unsigned index = j++;
- unsigned level = 1;
tree oldlist = TREE_VEC_ELT (ftparms, i);
tree list = rewrite_tparm_list (oldlist, index, level,
targs, i, complain);
@@ -30261,15 +30273,37 @@ type_targs_deducible_from (tree tmpl, tree type)
/* We don't fail on an undeduced targ the second time through (like
get_partial_spec_bindings) because we're going to try defaults. */
- if (!tried_array_deduction)
- for (int i = 0; i < len; ++i)
- if (! TREE_VEC_ELT (targs, i))
- {
- try_array_deduction (tparms, targs, TREE_TYPE (tmpl));
- tried_array_deduction = true;
- if (TREE_VEC_ELT (targs, i))
- goto again;
- }
+ for (int i = 0; i < len; ++i)
+ if (! TREE_VEC_ELT (targs, i))
+ {
+ tree tparm = TREE_VEC_ELT (tparms, i);
+ tparm = TREE_VALUE (tparm);
+
+ if (!tried_array_deduction
+ && TREE_CODE (tparm) == TYPE_DECL)
+ {
+ try_array_deduction (tparms, targs, TREE_TYPE (tmpl));
+ tried_array_deduction = true;
+ if (TREE_VEC_ELT (targs, i))
+ goto again;
+ }
+ /* If the type parameter is a parameter pack, then it will be deduced
+ to an empty parameter pack. This is another case that doesn't model
+ well as partial specialization. */
+ if (template_parameter_pack_p (tparm))
+ {
+ tree arg;
+ if (TREE_CODE (tparm) == TEMPLATE_PARM_INDEX)
+ {
+ arg = make_node (NONTYPE_ARGUMENT_PACK);
+ TREE_CONSTANT (arg) = 1;
+ }
+ else
+ arg = cxx_make_type (TYPE_ARGUMENT_PACK);
+ ARGUMENT_PACK_ARGS (arg) = make_tree_vec (0);
+ TREE_VEC_ELT (targs, i) = arg;
+ }
+ }
/* Maybe add in default template args. This seems like a flaw in the
specification in terms of partial specialization, since it says the
new file mode 100644
@@ -0,0 +1,7 @@
+// PR c++/109321
+// { dg-do compile { target c++20 } }
+
+struct A;
+template<class C1> struct B;
+template<class, class C2=A> using D = B<C2>;
+void f () { D() = 0; } // { dg-error "deduction failed|no match" }
new file mode 100644
@@ -0,0 +1,9 @@
+// PR c++/109320
+// { dg-do compile { target c++20 } }
+
+template<bool B>
+struct S {};
+template<int... C>
+using u = S<true>;
+struct X {};
+auto a = u {};