On Thu, 13 Jun 2024, Jason Merrill wrote:

> On 6/13/24 11:05, Patrick Palka wrote:
> > On Thu, 23 May 2024, Jason Merrill wrote:
> > 
> > > On 5/23/24 17:42, Patrick Palka wrote:
> > > > On Thu, 23 May 2024, Jason Merrill wrote:
> > > > 
> > > > > On 5/23/24 14:06, Patrick Palka wrote:
> > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> > > > > > OK for trunk/14?
> > > > > > 
> > > > > > -- >8 --
> > > > > > 
> > > > > > Here we're neglecting to update DECL_NAME during the alias CTAD
> > > > > > guide
> > > > > > transformation, which causes copy_guide_p to return false for the
> > > > > > transformed copy deduction guide since DECL_NAME is still __dguide_C
> > > > > > with TREE_TYPE C<B, T> but it should be __dguide_A with TREE_TYPE
> > > > > > A<T>
> > > > > > (equivalently C<false, T>).  This ultimately results in ambiguity
> > > > > > during
> > > > > > overload resolution between the copy deduction guide vs copy ctor
> > > > > > guide.
> > > > > > 
> > > > > > This patch makes us update DECL_NAME of a transformed guide
> > > > > > accordingly
> > > > > > during alias CTAD.  This eventually needs to be done for inherited
> > > > > > CTAD
> > > > > > too, but it's not clear what identifier to use there since it has to
> > > > > > be
> > > > > > unique for each derived/base pair.  For
> > > > > > 
> > > > > >      template<bool B, class T> struct A { ... };
> > > > > >      template<class T> struct B : A<false, T> { using A<false,
> > > > > > T>::A; }
> > > > > > 
> > > > > > at first glance it'd be reasonable to give inherited guides a name
> > > > > > of
> > > > > > __dguide_B with TREE_TYPE A<false, T>, but since that name is
> > > > > > already
> > > > > > used B's own guides its TREE_TYPE is already B<T>.
> > > > > 
> > > > > Why can't it be the same __dguide_B with TREE_TYPE B<T>?
> > > > 
> > > > Ah because copy_guide_p relies on TREE_TYPE in order to recognize a copy
> > > > deduction guide, and with that TREE_TYPE it would still incorrectly
> > > > return false for an inherited copy deduction guide, e.g.
> > > > 
> > > >     A(A<B, T>) -> A<B, T>
> > > > 
> > > > gets transformed into
> > > > 
> > > >     B(A<false, T>) -> B<T>
> > > > 
> > > > and A<false, T> != B<T> so copy_guide_p returns false.
> > > 
> > > Hmm, that seems correct; the transformed candidate is not the copy
> > > deduction
> > > guide for B.
> > 
> > By https://eel.is/c++draft/over.match.class.deduct#3.4 it seems that a
> > class template can now have multiple copy deduction guides with inherited
> > CTAD: the derived class's own copy guide, along with the transformed copy
> > guides of its eligible base classes.  Do we want to follow the standard
> > precisely here, or should we maybe restrict the copy-guideness propagation
> > to alias CTAD only?
> 
> The latter, I think; it seems nonsensical to have multiple copy guides.

Sounds good, so for inherited CTAD it should suffice to use __dguide_B
as the name (where B is the derived class), like so?

-- >8 --

Subject: [PATCH] c++: alias CTAD and copy deduction guide [PR115198]

Here we're neglecting to update DECL_NAME during the alias CTAD guide
transformation, which causes copy_guide_p to return false for the
transformed copy deduction guide since DECL_NAME is still __dguide_C
with TREE_TYPE C<B, T> but it should be __dguide_A with TREE_TYPE A<T>
(equivalently C<false, T>).  This ultimately results in ambiguity during
overload resolution between the copy deduction guide vs copy ctor guide.

This patch makes us update DECL_NAME of a transformed guide accordingly
during alias/inherited CTAD.

        PR c++/115198

gcc/cp/ChangeLog:

        * pt.cc (alias_ctad_tweaks): Update DECL_NAME of a transformed
        guide.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/class-deduction-alias22.C: New test.
---
 gcc/cp/pt.cc                                       |  6 +++++-
 .../g++.dg/cpp2a/class-deduction-alias22.C         | 14 ++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 607753ae6b7..daa8ac386dc 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -30342,13 +30342,14 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
      any).  */
 
   enum { alias, inherited } ctad_kind;
-  tree atype, fullatparms, utype;
+  tree atype, fullatparms, utype, name;
   if (TREE_CODE (tmpl) == TEMPLATE_DECL)
     {
       ctad_kind = alias;
       atype = TREE_TYPE (tmpl);
       fullatparms = DECL_TEMPLATE_PARMS (tmpl);
       utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+      name = dguide_name (tmpl);
     }
   else
     {
@@ -30356,6 +30357,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
       atype = NULL_TREE;
       fullatparms = TREE_PURPOSE (tmpl);
       utype = TREE_VALUE (tmpl);
+      name = dguide_name (TPARMS_PRIMARY_TEMPLATE
+                         (INNERMOST_TEMPLATE_PARMS (fullatparms)));
     }
 
   tsubst_flags_t complain = tf_warning_or_error;
@@ -30451,6 +30454,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
            }
          if (g == error_mark_node)
            continue;
+         DECL_NAME (g) = name;
          if (nfparms == 0)
            {
              /* The targs are all non-dependent, so g isn't a template.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C 
b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
new file mode 100644
index 00000000000..9c6c841166a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias22.C
@@ -0,0 +1,14 @@
+// PR c++/115198
+// { dg-do compile { target c++20 } }
+
+template<bool B, class T>
+struct C {
+  C() = default;
+  C(const C&) = default;
+};
+
+template<class T>
+using A = C<false, T>;
+
+C<false, int> c;
+A a = c; // { dg-bogus "ambiguous" }
-- 
2.45.2.492.gd63586cb31


> 
> Jason
> 
> > > > But it just occurred to me that this TREE_TYPE clobbering of the
> > > > __dguide_foo identifier already happens if we have two class templates
> > > > with the same name in different namespaces, since the identifier
> > > > contains only the terminal name.  Maybe this suggests that we should
> > > > use a tree flag to track whether a guide is the copy deduction guide
> > > > instead of setting TREE_TYPE of DECL_NAME?
> > > 
> > > Good point.
> > > 
> > > Jason
> > > 
> > > 
> > 
> 
> 

Reply via email to