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.