On Fri, 20 Sep 2024, Jason Merrill wrote:

> On 9/18/24 10:59 PM, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
> > look OK for trunk?  I'm not sure this is worth backporting
> > without the previous CWG 2273 tweak since it'll mean inconsistent
> > behavior between implict vs explicit object members in GCC 14: the call
> > to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
> > 2273 tiebreaker incorrectly triggering), while the g() and h() calls
> > would be ambiguous (since that tiebreaker doesn't consider object
> > correspondence).
> 
> Agreed, I wouldn't backport.

What do you think about enforcing this part of CWG 2789 only for
constructors in GCC 14?  That would sidestep the inconsistency that
arises if we don't also backport the CWG 2273, and still fix the
testcase in the PR.

Like so?

-- >8 --

Subject: [PATCH GCC 14] c++: CWG 2789 and usings [PR116492]

For GCC 14, narrowly fix this PR by enforcing the unimplemented

  - if they are member functions, both are direct members of the same
    class, and

part of CWG 2789 for constructors only.

        PR c++/116492
        DR 2789

gcc/cp/ChangeLog:

        * call.cc (cand_parms_match): Return false for constructors that
        come from different classes.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
---
 gcc/cp/call.cc                                   |  4 ++++
 .../g++.dg/cpp2a/concepts-inherit-ctor12.C       | 16 ++++++++++++++++
 2 files changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 0f4eeeb5395..5c7aaa6dcf1 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12826,6 +12826,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, 
pmatch match_kind)
        && DECL_FUNCTION_MEMBER_P (fn2)))
     /* Early escape.  */;
 
+  else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
+          && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
+              != DECL_CONTEXT (strip_inheriting_ctors (fn2))))
+    return false;
   /* CWG2789 is not adequate, it should specify corresponding object
      parameters, not same typed object parameters.  */
   else if (!object_parms_correspond (c1, fn1, c2, fn2))
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
new file mode 100644
index 00000000000..3e5dbfc37ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
@@ -0,0 +1,16 @@
+// PR c++/116492
+// CWG 2789
+// { dg-do compile { target c++20 } }
+
+template<class T>
+struct A {
+  A() requires true = delete;
+};
+
+struct B : A<int> {
+  B();
+  using A<int>::A;
+};
+
+B b; // OK, selects the non-inherited constructor over the more constrained
+     // inherited constructor.
-- 
2.46.1.565.g6531f31ef3



> 
> > Also I'm not 100% sure if I'm interpreting "both are direct members of
> > the same class" correctly here to mean ruling out using'd vs non-using'd
> > members, since https://eel.is/c++draft/namespace.udecl#note-5 says
> > using'd members are "treated as though they were direct members of the
> > derived class"...?
> 
> Looking back at the CWG wiki notes, I see that ruling out using vs non-using
> was intended.
> 
> > +++ b/gcc/cp/call.cc
> > @@ -12893,16 +12872,19 @@ cand_parms_match (z_candidate *c1, z_candidate
> > *c2, pmatch match_kind)
> >     tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
> >     tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
> >   +  if (DECL_FUNCTION_MEMBER_P (fn1)
> > +      && DECL_FUNCTION_MEMBER_P (fn2))
> >       {
> > +      tree base1 = DECL_CONTEXT (strip_inheriting_ctors (fn1));
> > +      tree base2 = DECL_CONTEXT (strip_inheriting_ctors (fn2));
> > +      if (base1 != base2)
> > +   return false;
> > +
> > +      /* CWG2789 is not adequate, it should specify corresponding object
> > +    parameters, not same typed object parameters.  */
> 
> With this change, the difference is no longer significant; the comment should
> change to something like
> 
> /* Use object_parms_correspond to simplify comparing iobj/xobj/static
>    member functions.  */
> 
> > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C
> > @@ -20,12 +23,14 @@ struct S : B<> {
> >     constexpr operator int () const { return 10; }
> >     constexpr int g() { return 10; }
> >     constexpr int h(this S&&) { return 10; }
> > +  // { dg-warning "explicit object" "" { target c++20_only } .-1 }
> >   };
> >   -// implicit object parms match, B::f is more constrained
> > -static_assert(S<>{}.f() == 5);
> > -static_assert(S<>{}.g() == 5);
> > -static_assert(S<>{}.h() == 5);
> > +// ambiguous, constraints aren't considered since the candidates
> > +// are defined from different classes
> 
> "defined in" or "come from"
> 
> OK with these two tweaks.

Thanks, pushed to trunk with those changes.

> 
> Jason
> 
> 

Reply via email to