diff mbox series

c++: fix ICE on friend with explicit object parameter [PR-122258]

Message ID 20260903061027.50275-1-imlunex2011@gmail.com
State New
Headers show
Series c++: fix ICE on friend with explicit object parameter [PR-122258] | expand

Commit Message

imlunex2011@gmail.com Sept. 3, 2026, 6:10 a.m. UTC
From: Lunex <imlunex2011@gmail.com>

Hope you are well,

So this is patch and here is what it is about -

A 'friend' is not a member but 'this Self &&' only works for members.
GCC missed this check, so it marked the friend as a member
and later crashed with no access info to check.

Now we reject friend functions that use an explicit object parameter,

gcc/cp/ChangeLog:

	PR c++/122258
	* decl.cc (grokdeclarator): Diagnose friend with explicit object
	parameter.

gcc/testsuite/ChangeLog:

	PR c++/122258
	* g++.dg/cpp23/explicit-obj-diagnostics13.C: New test.
---
 gcc/cp/decl.cc                                |  7 ++++
 .../g++.dg/cpp23/explicit-obj-diagnostics13.C | 37 +++++++++++++++++++
 2 files changed, 44 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C

Comments

Jason Merrill Sept. 3, 2026, 5:47 p.m. UTC | #1
On 9/3/26 2:10 AM, imlunex2011@gmail.com wrote:
> From: Lunex <imlunex2011@gmail.com>
> 
> Hope you are well,
> 
> So this is patch and here is what it is about -
> 
> A 'friend' is not a member but 'this Self &&' only works for members.
> GCC missed this check, so it marked the friend as a member
> and later crashed with no access info to check.
> 
> Now we reject friend functions that use an explicit object parameter,
> 
> gcc/cp/ChangeLog:
> 
> 	PR c++/122258
> 	* decl.cc (grokdeclarator): Diagnose friend with explicit object
> 	parameter.

It should be OK for a friend to have an xobj parameter if it's a member 
of another class.  The problem here is that it's a non-member function 
that the existing check isn't catching.

How does

>                 if (!ctype
>                     && decl_context == NORMAL
>                     && (in_namespace
>                         || !declarator->declarator->u.id.qualifying_scope))

need to change to cover this case?

Jason
diff mbox series

Patch

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 55badc9ee..246642aea 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -15673,6 +15673,13 @@  grokdeclarator (const cp_declarator *declarator,
 		  error_at (DECL_SOURCE_LOCATION (xobj_parm),
 			    "a non-member function cannot have "
 			    "an explicit object parameter");
+		else if (friendp)
+		  {
+		    error_at (DECL_SOURCE_LOCATION (xobj_parm),
+			      "a friend 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 000000000..1434ad252
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics13.C
@@ -0,0 +1,37 @@ 
+// P0847R7
+// { dg-do compile { target c++23 } }
+
+#include <tuple>
+
+// 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 friend function cannot have an explicit object parameter" }
+};
+
+struct S {
+  friend void f(this S &); // { dg-error "a friend function cannot have an explicit object parameter" }
+  friend void g(this S &&); // { dg-error "a friend function cannot have an explicit object parameter" }
+};
+
+struct U {
+  template<class Self>
+  friend void h(this Self &&); // { dg-error "a friend function cannot have an explicit object parameter" }
+  template<class Self>
+  friend void k(this Self &&) {} // { dg-error "a friend function cannot have an explicit object parameter" }
+};
+
+struct V {
+  friend void m(this V &) {} // { dg-error "a friend function cannot have an explicit object parameter" }
+};
+
+namespace std {
+template<> struct tuple_size<type> : integral_constant<size_t, 1> {};
+template<size_t I> struct tuple_element<I, type> { using type = int; };
+}
+
+void test_sb()
+{
+  auto [a] = type();
+}