c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal

Message ID ZaE0eq4+3Fn78jqj@tucnak
State Unresolved
Headers
Series c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Jakub Jelinek Jan. 12, 2024, 12:45 p.m. UTC
  Hi!

The following patch attempts to implement what apparently clang++
implemented for explicit object member function mangling, but nobody
actually proposed in patch form in
https://github.com/itanium-cxx-abi/cxx-abi/issues/148

Ok for trunk if it passes full bootstrap/regtest?  So far just tested
on the new testcases.

2024-01-12  Jakub Jelinek  <jakub@redhat.com>

gcc/cp/
	* mangle.cc (write_nested_name): Mangle explicit object
	member functions with H as per
	https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal.
gcc/testsuite/
	* g++.dg/abi/mangle79.C: New test.
include/
	* demangle.h (enum demangle_component_type): Add
	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
libiberty/
	* cp-demangle.c (FNQUAL_COMPONENT_CASE): Add case for
	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
	(d_dump): Handle DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
	(d_nested_name): Parse H after N in nested name.
	(d_count_templates_scopes): Handle
	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
	(d_print_mod): Likewise.
	(d_print_function_type): Likewise.
	* testsuite/demangle-expected: Add tests for explicit object
	member functions.


	Jakub
  

Comments

Jason Merrill Jan. 12, 2024, 1:48 p.m. UTC | #1
On 1/12/24 07:45, Jakub Jelinek wrote:
> Hi!
> 
> The following patch attempts to implement what apparently clang++
> implemented for explicit object member function mangling, but nobody
> actually proposed in patch form in
> https://github.com/itanium-cxx-abi/cxx-abi/issues/148
> 
> Ok for trunk if it passes full bootstrap/regtest?  So far just tested
> on the new testcases.

OK, thanks.

> 2024-01-12  Jakub Jelinek  <jakub@redhat.com>
> 
> gcc/cp/
> 	* mangle.cc (write_nested_name): Mangle explicit object
> 	member functions with H as per
> 	https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal.
> gcc/testsuite/
> 	* g++.dg/abi/mangle79.C: New test.
> include/
> 	* demangle.h (enum demangle_component_type): Add
> 	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> libiberty/
> 	* cp-demangle.c (FNQUAL_COMPONENT_CASE): Add case for
> 	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> 	(d_dump): Handle DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> 	(d_nested_name): Parse H after N in nested name.
> 	(d_count_templates_scopes): Handle
> 	DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION.
> 	(d_print_mod): Likewise.
> 	(d_print_function_type): Likewise.
> 	* testsuite/demangle-expected: Add tests for explicit object
> 	member functions.
> 
> --- gcc/cp/mangle.cc.jj	2024-01-12 10:07:31.248231747 +0100
> +++ gcc/cp/mangle.cc	2024-01-12 11:37:35.790915463 +0100
> @@ -1247,6 +1247,8 @@ write_nested_name (const tree decl)
>   	    write_char ('R');
>   	}
>       }
> +  else if (DECL_XOBJ_MEMBER_FUNCTION_P (decl))
> +    write_char ('H');
>   
>     /* Is this a template instance?  */
>     if (tree info = maybe_template_info (decl))
> --- gcc/testsuite/g++.dg/abi/mangle79.C.jj	2024-01-12 13:18:20.782917924 +0100
> +++ gcc/testsuite/g++.dg/abi/mangle79.C	2024-01-12 13:26:01.297433970 +0100
> @@ -0,0 +1,61 @@
> +// { dg-do compile { target c++11 } }
> +// { dg-options "" }
> +
> +struct S {
> +  static void foo (S);
> +  void foo (this S);		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +  template <int N, typename T>
> +  static void bar (S, T);
> +  template <int N, typename T>
> +  void bar (this S, T);		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +  static void baz (const S &);
> +  void baz (this const S &);	// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +};
> +
> +void
> +S::foo (S)
> +{
> +}
> +
> +void
> +S::foo (this S)			// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +{
> +}
> +
> +template <int N, typename T>
> +void
> +S::bar (S, T)
> +{
> +}
> +
> +template <int N, typename T>
> +void
> +S::bar (this S, T)		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +{
> +}
> +
> +void
> +S::baz (const S &)
> +{
> +}
> +
> +void
> +S::baz (this const S &)		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
> +{
> +}
> +
> +void
> +qux (S *p)
> +{
> +  S::foo (*p);
> +  p->foo ();
> +  S::bar <5> (*p, 0);
> +  p->bar <5> (0);
> +}
> +
> +// { dg-final { scan-assembler "_ZN1S3fooES_" } }
> +// { dg-final { scan-assembler "_ZNH1S3fooES_" } }
> +// { dg-final { scan-assembler "_ZN1S3barILi5EiEEvS_T0_" } }
> +// { dg-final { scan-assembler "_ZNH1S3barILi5EiEEvS_T0_" } }
> +// { dg-final { scan-assembler "_ZN1S3bazERKS_" } }
> +// { dg-final { scan-assembler "_ZNH1S3bazERKS_" } }
> --- include/demangle.h.jj	2024-01-03 12:07:25.330409694 +0100
> +++ include/demangle.h	2024-01-12 11:43:27.543915280 +0100
> @@ -314,6 +314,8 @@ enum demangle_component_type
>     /* C++11: An rvalue reference modifying a member function.  The one
>        subtree is the type which is being referenced.  */
>     DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS,
> +  /* C++23: A member function with explict object parameter.  */
> +  DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION,
>     /* A vendor qualifier.  The left subtree is the type which is being
>        qualified, and the right subtree is the name of the
>        qualifier.  */
> --- libiberty/cp-demangle.c.jj	2024-01-03 12:07:48.498085118 +0100
> +++ libiberty/cp-demangle.c	2024-01-12 13:06:04.526281733 +0100
> @@ -581,6 +581,7 @@ static char *d_demangle (const char *, i
>       case DEMANGLE_COMPONENT_CONST_THIS:			\
>       case DEMANGLE_COMPONENT_REFERENCE_THIS:		\
>       case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:	\
> +    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:	\
>       case DEMANGLE_COMPONENT_TRANSACTION_SAFE:		\
>       case DEMANGLE_COMPONENT_NOEXCEPT:			\
>       case DEMANGLE_COMPONENT_THROW_SPEC
> @@ -749,6 +750,9 @@ d_dump (struct demangle_component *dc, i
>       case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
>         printf ("rvalue reference this\n");
>         break;
> +    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
> +      printf ("explicit object parameter\n");
> +      break;
>       case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
>         printf ("transaction_safe this\n");
>         break;
> @@ -1547,6 +1551,8 @@ d_name (struct d_info *di, int substable
>   
>   /* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
>                    ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
> +                 ::= N H <prefix> <unqualified-name> E
> +                 ::= N H <template-prefix> <template-args> E
>   */
>   
>   static struct demangle_component *
> @@ -1559,13 +1565,24 @@ d_nested_name (struct d_info *di)
>     if (! d_check_char (di, 'N'))
>       return NULL;
>   
> -  pret = d_cv_qualifiers (di, &ret, 1);
> -  if (pret == NULL)
> -    return NULL;
> +  if (d_peek_char (di) == 'H')
> +    {
> +      d_advance (di, 1);
> +      di->expansion += sizeof "this";
> +      pret = &ret;
> +      rqual = d_make_comp (di, DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION,
> +			   NULL, NULL);
> +    }
> +  else
> +    {
> +      pret = d_cv_qualifiers (di, &ret, 1);
> +      if (pret == NULL)
> +	return NULL;
>   
> -  /* Parse the ref-qualifier now and then attach it
> -     once we have something to attach it to.  */
> -  rqual = d_ref_qualifier (di, NULL);
> +      /* Parse the ref-qualifier now and then attach it
> +	 once we have something to attach it to.  */
> +      rqual = d_ref_qualifier (di, NULL);
> +    }
>   
>     *pret = d_prefix (di, 1);
>     if (*pret == NULL)
> @@ -4427,6 +4444,7 @@ d_count_templates_scopes (struct d_print
>       case DEMANGLE_COMPONENT_CONST_THIS:
>       case DEMANGLE_COMPONENT_REFERENCE_THIS:
>       case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
> +    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
>       case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
>       case DEMANGLE_COMPONENT_NOEXCEPT:
>       case DEMANGLE_COMPONENT_THROW_SPEC:
> @@ -6521,6 +6539,8 @@ d_print_mod (struct d_print_info *dpi, i
>       case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
>         d_append_string (dpi, "&&");
>         return;
> +    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
> +      return;
>       case DEMANGLE_COMPONENT_COMPLEX:
>         d_append_string (dpi, " _Complex");
>         return;
> @@ -6559,11 +6579,13 @@ d_print_function_type (struct d_print_in
>   {
>     int need_paren;
>     int need_space;
> +  int xobj_memfn;
>     struct d_print_mod *p;
>     struct d_print_mod *hold_modifiers;
>   
>     need_paren = 0;
>     need_space = 0;
> +  xobj_memfn = 0;
>     for (p = mods; p != NULL; p = p->next)
>       {
>         if (p->printed)
> @@ -6586,7 +6608,8 @@ d_print_function_type (struct d_print_in
>   	  need_space = 1;
>   	  need_paren = 1;
>   	  break;
> -	FNQUAL_COMPONENT_CASE:
> +	case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
> +	  xobj_memfn = 1;
>   	  break;
>   	default:
>   	  break;
> @@ -6617,6 +6640,8 @@ d_print_function_type (struct d_print_in
>       d_append_char (dpi, ')');
>   
>     d_append_char (dpi, '(');
> +  if (xobj_memfn)
> +    d_append_string (dpi, "this ");
>   
>     if (d_right (dc) != NULL)
>       d_print_comp (dpi, options, d_right (dc));
> --- libiberty/testsuite/demangle-expected.jj	2023-12-03 17:44:57.266453553 +0100
> +++ libiberty/testsuite/demangle-expected	2024-01-12 12:22:56.647587418 +0100
> @@ -1700,3 +1700,12 @@ void f<int>() requires C<int>
>   # requires after ()
>   _Z1fIiEvvQ1CIT_E
>   void f<int>() requires C<int>
> +
> +_ZNH1S3fooES_
> +S::foo(this S)
> +
> +_ZNH1S3barILi5EiEEvS_T0_
> +void S::bar<5, int>(this S, int)
> +
> +_ZNH1S3bazERKS_
> +S::baz(this S const&)
> 
> 	Jakub
>
  

Patch

--- gcc/cp/mangle.cc.jj	2024-01-12 10:07:31.248231747 +0100
+++ gcc/cp/mangle.cc	2024-01-12 11:37:35.790915463 +0100
@@ -1247,6 +1247,8 @@  write_nested_name (const tree decl)
 	    write_char ('R');
 	}
     }
+  else if (DECL_XOBJ_MEMBER_FUNCTION_P (decl))
+    write_char ('H');
 
   /* Is this a template instance?  */
   if (tree info = maybe_template_info (decl))
--- gcc/testsuite/g++.dg/abi/mangle79.C.jj	2024-01-12 13:18:20.782917924 +0100
+++ gcc/testsuite/g++.dg/abi/mangle79.C	2024-01-12 13:26:01.297433970 +0100
@@ -0,0 +1,61 @@ 
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S {
+  static void foo (S);
+  void foo (this S);		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+  template <int N, typename T>
+  static void bar (S, T);
+  template <int N, typename T>
+  void bar (this S, T);		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+  static void baz (const S &);
+  void baz (this const S &);	// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+};
+
+void
+S::foo (S)
+{
+}
+
+void
+S::foo (this S)			// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+{
+}
+
+template <int N, typename T>
+void
+S::bar (S, T)
+{
+}
+
+template <int N, typename T>
+void
+S::bar (this S, T)		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+{
+}
+
+void
+S::baz (const S &)
+{
+}
+
+void
+S::baz (this const S &)		// { dg-warning "explicit object member function only available with" "" { target c++20_down } }
+{
+}
+
+void
+qux (S *p)
+{
+  S::foo (*p);
+  p->foo ();
+  S::bar <5> (*p, 0);
+  p->bar <5> (0);
+}
+
+// { dg-final { scan-assembler "_ZN1S3fooES_" } }
+// { dg-final { scan-assembler "_ZNH1S3fooES_" } }
+// { dg-final { scan-assembler "_ZN1S3barILi5EiEEvS_T0_" } }
+// { dg-final { scan-assembler "_ZNH1S3barILi5EiEEvS_T0_" } }
+// { dg-final { scan-assembler "_ZN1S3bazERKS_" } }
+// { dg-final { scan-assembler "_ZNH1S3bazERKS_" } }
--- include/demangle.h.jj	2024-01-03 12:07:25.330409694 +0100
+++ include/demangle.h	2024-01-12 11:43:27.543915280 +0100
@@ -314,6 +314,8 @@  enum demangle_component_type
   /* C++11: An rvalue reference modifying a member function.  The one
      subtree is the type which is being referenced.  */
   DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS,
+  /* C++23: A member function with explict object parameter.  */
+  DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION,
   /* A vendor qualifier.  The left subtree is the type which is being
      qualified, and the right subtree is the name of the
      qualifier.  */
--- libiberty/cp-demangle.c.jj	2024-01-03 12:07:48.498085118 +0100
+++ libiberty/cp-demangle.c	2024-01-12 13:06:04.526281733 +0100
@@ -581,6 +581,7 @@  static char *d_demangle (const char *, i
     case DEMANGLE_COMPONENT_CONST_THIS:			\
     case DEMANGLE_COMPONENT_REFERENCE_THIS:		\
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:	\
+    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:	\
     case DEMANGLE_COMPONENT_TRANSACTION_SAFE:		\
     case DEMANGLE_COMPONENT_NOEXCEPT:			\
     case DEMANGLE_COMPONENT_THROW_SPEC
@@ -749,6 +750,9 @@  d_dump (struct demangle_component *dc, i
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
       printf ("rvalue reference this\n");
       break;
+    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
+      printf ("explicit object parameter\n");
+      break;
     case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
       printf ("transaction_safe this\n");
       break;
@@ -1547,6 +1551,8 @@  d_name (struct d_info *di, int substable
 
 /* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
                  ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
+                 ::= N H <prefix> <unqualified-name> E
+                 ::= N H <template-prefix> <template-args> E
 */
 
 static struct demangle_component *
@@ -1559,13 +1565,24 @@  d_nested_name (struct d_info *di)
   if (! d_check_char (di, 'N'))
     return NULL;
 
-  pret = d_cv_qualifiers (di, &ret, 1);
-  if (pret == NULL)
-    return NULL;
+  if (d_peek_char (di) == 'H')
+    {
+      d_advance (di, 1);
+      di->expansion += sizeof "this";
+      pret = &ret;
+      rqual = d_make_comp (di, DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION,
+			   NULL, NULL);
+    }
+  else
+    {
+      pret = d_cv_qualifiers (di, &ret, 1);
+      if (pret == NULL)
+	return NULL;
 
-  /* Parse the ref-qualifier now and then attach it
-     once we have something to attach it to.  */
-  rqual = d_ref_qualifier (di, NULL);
+      /* Parse the ref-qualifier now and then attach it
+	 once we have something to attach it to.  */
+      rqual = d_ref_qualifier (di, NULL);
+    }
 
   *pret = d_prefix (di, 1);
   if (*pret == NULL)
@@ -4427,6 +4444,7 @@  d_count_templates_scopes (struct d_print
     case DEMANGLE_COMPONENT_CONST_THIS:
     case DEMANGLE_COMPONENT_REFERENCE_THIS:
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
     case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
     case DEMANGLE_COMPONENT_NOEXCEPT:
     case DEMANGLE_COMPONENT_THROW_SPEC:
@@ -6521,6 +6539,8 @@  d_print_mod (struct d_print_info *dpi, i
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
       d_append_string (dpi, "&&");
       return;
+    case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
+      return;
     case DEMANGLE_COMPONENT_COMPLEX:
       d_append_string (dpi, " _Complex");
       return;
@@ -6559,11 +6579,13 @@  d_print_function_type (struct d_print_in
 {
   int need_paren;
   int need_space;
+  int xobj_memfn;
   struct d_print_mod *p;
   struct d_print_mod *hold_modifiers;
 
   need_paren = 0;
   need_space = 0;
+  xobj_memfn = 0;
   for (p = mods; p != NULL; p = p->next)
     {
       if (p->printed)
@@ -6586,7 +6608,8 @@  d_print_function_type (struct d_print_in
 	  need_space = 1;
 	  need_paren = 1;
 	  break;
-	FNQUAL_COMPONENT_CASE:
+	case DEMANGLE_COMPONENT_XOBJ_MEMBER_FUNCTION:
+	  xobj_memfn = 1;
 	  break;
 	default:
 	  break;
@@ -6617,6 +6640,8 @@  d_print_function_type (struct d_print_in
     d_append_char (dpi, ')');
 
   d_append_char (dpi, '(');
+  if (xobj_memfn)
+    d_append_string (dpi, "this ");
 
   if (d_right (dc) != NULL)
     d_print_comp (dpi, options, d_right (dc));
--- libiberty/testsuite/demangle-expected.jj	2023-12-03 17:44:57.266453553 +0100
+++ libiberty/testsuite/demangle-expected	2024-01-12 12:22:56.647587418 +0100
@@ -1700,3 +1700,12 @@  void f<int>() requires C<int>
 # requires after ()
 _Z1fIiEvvQ1CIT_E
 void f<int>() requires C<int>
+
+_ZNH1S3fooES_
+S::foo(this S)
+
+_ZNH1S3barILi5EiEEvS_T0_
+void S::bar<5, int>(this S, int)
+
+_ZNH1S3bazERKS_
+S::baz(this S const&)