On 9/4/26 8:26 AM, [email protected] wrote:
From: Lunex <[email protected]>
a friend which is not a member but 'this Self &&' was used on that that
is only for members. GCC faild 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.
For future reference, please wrap the commit message at 76 columns, and
keep subject line (after [PATCH]) as close to 50 as is reasonable.
@@ -15666,13 +15666,18 @@ grokdeclarator (const cp_declarator *declarator,
if (xobj_parm)
{
- if (!ctype
+ if ((!ctype
&& decl_context == NORMAL
I think it's simpler to change only this line, so I'm pushing the
following. Thanks!
Jason
From 9971faf312bfa502d8c983b528f80e4538cfefaf Mon Sep 17 00:00:00 2001
From: Lunex <[email protected]>
Date: Fri, 4 Sep 2026 18:26:35 +0600
Subject: [PATCH] c++: friend with explicit object parameter [PR122258]
To: [email protected]
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]>
---
gcc/cp/decl.cc | 11 ++--
.../g++.dg/cpp23/explicit-obj-diagnostics13.C | 66 +++++++++++++++++++
2 files changed, 73 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 6e45321e971..ff8e3fd2119 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 00000000000..00f55cbfc9d
--- /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&);
+ };
+}
--
2.55.0