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