https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125826

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Trying now
--- gcc/cp/method.cc.jj 2026-06-25 00:10:29.208325952 +0200
+++ gcc/cp/method.cc    2026-06-30 18:54:35.753533242 +0200
@@ -3768,6 +3768,22 @@ maybe_delete_defaulted_fn (tree fn, tree
     = TREE_VALUE (DECL_XOBJ_MEMBER_FUNCTION_P (fn)
                  ? TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)))
                  : FUNCTION_FIRST_USER_PARMTYPE (fn));
+  tree implicit_parmtype
+    = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (implicit_fn));
+  auto bad_xobj_parm = [](tree fn, tree implicit_fn) {
+    tree fn_parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
+    if (!DECL_XOBJ_MEMBER_FUNCTION_P (fn))
+      return false;
+
+    tree fn_obj_ref_type = TREE_VALUE (fn_parms);
+    if (!TYPE_REF_P (fn_obj_ref_type)
+       || TYPE_REF_IS_RVALUE (fn_obj_ref_type)
+       || !object_parms_correspond (fn, implicit_fn,
+                                    DECL_CONTEXT (implicit_fn)))
+      return true;
+    return false;
+  };
+
   if (/* [dcl.fct.def.default] "if F1 is an assignment operator"...  */
       (SFK_ASSIGN_P (kind)
        /* "and the return type of F1 differs from the return type of F2"  */
@@ -3778,7 +3794,17 @@ maybe_delete_defaulted_fn (tree fn, tree
           || !TYPE_REF_P (parmtype)))
       /* If F1 is *not* explicitly defaulted on its first declaration, the
         program is ill-formed.  */
-      || !DECL_DEFAULTED_IN_CLASS_P (fn))
+      || !DECL_DEFAULTED_IN_CLASS_P (fn)
+      || (cxx_dialect >= cxx29
+         /* For C++29, the only case which is deleted rather than
+            ill-formed is when F1 has const C & argument and F2 C &
+            and no other non-allowed differences.  */
+         && (FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn))
+             || !SFK_ASSIGN_P (kind)
+             || bad_xobj_parm (fn, implicit_fn)
+             || TYPE_REF_IS_RVALUE (parmtype)
+             || TYPE_QUALS (TREE_TYPE (parmtype)) != TYPE_QUAL_CONST
+             || TYPE_QUALS (TREE_TYPE (implicit_parmtype)))))
     {
       error ("defaulted declaration %q+D does not match the expected "
             "signature", fn);
@@ -3892,7 +3918,8 @@ defaulted_late_check (tree fn, tristate

   if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)),
                    TREE_TYPE (TREE_TYPE (implicit_fn)))
-      || !compare_fn_params (fn, implicit_fn))
+      || !compare_fn_params (fn, implicit_fn)
+      || (cxx_dialect >= cxx29 && FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (fn))))
     maybe_delete_defaulted_fn (fn, implicit_fn);

   if (DECL_DELETED_FN (implicit_fn))

First will need to deal with the
FAIL: g++.dg/cpp0x/defaulted51.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted52.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted54.C  -std=c++29  (test for errors, line 19)
FAIL: g++.dg/cpp0x/defaulted54.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted55.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29  (test for warnings, line 9)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29  (test for warnings, line 18)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29  (test for warnings, line 27)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29  (test for warnings, line 32)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29  (test for warnings, line 37)
FAIL: g++.dg/cpp0x/defaulted63.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted56.C  -std=c++29  at line 15 (test for warnings,
line 14)
FAIL: g++.dg/cpp0x/defaulted56.C  -std=c++29  at line 21 (test for warnings,
line 20)
FAIL: g++.dg/cpp0x/defaulted56.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted64.C  -std=c++29  (test for warnings, line 17)
FAIL: g++.dg/cpp0x/defaulted64.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted57.C  -std=c++29  at line 15 (test for warnings,
line 14)
FAIL: g++.dg/cpp0x/defaulted57.C  -std=c++29  at line 21 (test for warnings,
line 20)
FAIL: g++.dg/cpp0x/defaulted57.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted65.C  -std=c++29  at line 12 (test for warnings,
line 11)
FAIL: g++.dg/cpp0x/defaulted65.C  -std=c++29  at line 18 (test for warnings,
line 17)
FAIL: g++.dg/cpp0x/defaulted65.C  -std=c++29  at line 24 (test for warnings,
line 23)
FAIL: g++.dg/cpp0x/defaulted65.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted66.C  -std=c++29  at line 14 (test for warnings,
line 13)
FAIL: g++.dg/cpp0x/defaulted66.C  -std=c++29  at line 27 (test for warnings,
line 26)
FAIL: g++.dg/cpp0x/defaulted66.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted59.C  -std=c++29  at line 12 (test for warnings,
line 11)
FAIL: g++.dg/cpp0x/defaulted59.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted67.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted68.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp0x/defaulted15.C  -std=c++29  at line 52 (test for warnings,
line 51)
FAIL: g++.dg/cpp0x/defaulted15.C  -std=c++29 (test for excess errors)
FAIL: g++.dg/cpp1y/defaulted2.C  -std=c++29  at line 8 (test for warnings, line
7)
FAIL: g++.dg/cpp1y/defaulted2.C  -std=c++29  (test for errors, line 13)
FAIL: g++.dg/cpp1y/defaulted2.C  -std=c++29 (test for excess errors)
testsuite tweaks and then add testcases for anything not covered yet.

Reply via email to