diff mbox series

[pushed] c++: alias ctad refinements [PR109321]

Message ID 20230329022327.99330-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: alias ctad refinements [PR109321] | expand

Commit Message

Jason Merrill March 29, 2023, 2:23 a.m. UTC
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
diff mbox series

Patch

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3bb98ebeac1..e514a277872 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -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
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias16.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias16.C
new file mode 100644
index 00000000000..53d305b5c71
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias16.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias17.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias17.C
new file mode 100644
index 00000000000..b8346895b5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias17.C
@@ -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 {};