On Thu, 13 Jun 2024, Patrick Palka wrote:

> 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?

Ping.

> 
> -- >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