https://gcc.gnu.org/g:9971faf312bfa502d8c983b528f80e4538cfefaf
commit r17-3994-g9971faf312bfa502d8c983b528f80e4538cfefaf Author: Lunex <[email protected]> Date: Fri Sep 4 18:26:35 2026 +0600 c++: friend with explicit object parameter [PR122258] A friend which is not a member but 'this Self &&' was used on that that is only for members. GCC failed to check and later it crashed with no access info to check. Now we just reject only [non-member]friend that uses an explicit object parameter. PR c++/122258 gcc/cp/ChangeLog: * decl.cc (grokdeclarator): Extend non-member explicit object parameter check to include unqualified friends and clear is_xobj_member_function. gcc/testsuite/ChangeLog: * g++.dg/cpp23/explicit-obj-diagnostics13.C: New test. Co-authored-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/decl.cc | 11 ++-- .../g++.dg/cpp23/explicit-obj-diagnostics13.C | 66 ++++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 6e45321e9710..ff8e3fd2119f 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -15678,12 +15678,15 @@ grokdeclarator (const cp_declarator *declarator, if (xobj_parm) { if (!ctype - && decl_context == NORMAL + && (decl_context == NORMAL || friendp) && (in_namespace || !declarator->declarator->u.id.qualifying_scope)) - error_at (DECL_SOURCE_LOCATION (xobj_parm), - "a non-member function cannot have " - "an explicit object parameter"); + { + error_at (DECL_SOURCE_LOCATION (xobj_parm), + "a non-member function cannot have " + "an explicit object parameter"); + is_xobj_member_function = false; + } else { if (virtualp) diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C new file mode 100644 index 000000000000..00f55cbfc9de --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C @@ -0,0 +1,66 @@ +// P0847R7 +// { dg-do compile { target c++23 } } + +namespace std { + template<typename T> struct tuple_size; + template<int, typename> struct tuple_element; +} + +// PR c++/122258 - friend with explicit object param must be rejected + +struct type { + template<unsigned I, class Self> + friend auto get(this Self &&self) { return 0; } // { dg-error "a non-member function cannot have an explicit object parameter" } +}; + +struct S { + friend void f(this S &); // { dg-error "a non-member function cannot have an explicit object parameter" } + friend void g(this S &&); // { dg-error "a non-member function cannot have an explicit object parameter" } +}; + +struct U { + template<class Self> + friend void h(this Self &&); // { dg-error "a non-member function cannot have an explicit object parameter" } + template<class Self> + friend void k(this Self &&) {} // { dg-error "a non-member function cannot have an explicit object parameter" } +}; + +struct V { + friend void m(this V &) {} // { dg-error "a non-member function cannot have an explicit object parameter" } +}; + +struct Mem { + void mem(this Mem&); +}; + +struct A { + friend void Mem::mem(this Mem&); +}; + +struct B { + friend void Mem::mem(this Mem&); +}; + +struct C { + friend void Mem::mem(this Mem&); +}; + +namespace std { +template<> struct tuple_size<type> { static const int value = 1; }; +template<int I> struct tuple_element<I, type> { using type = int; }; +} + +void test_sb() +{ + auto [a] = type(); +} + +void test_friend_member(void) +{ + struct Mem2 { + void mem(this Mem2&); + }; + struct A { + friend void Mem2::mem(this Mem2&); + }; +}
