From 65388b28656d65595bdaf191df85af81c35ca638 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 13 Jan 2024 10:23:53 +0100 Subject: [PATCH] c++, demangle: Implement https://github.com/itanium-cxx-abi/cxx-abi/issues/148 non-proposal 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 2024-01-13 Jakub Jelinek 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 | 3 ++ gcc/testsuite/g++.dg/abi/mangle79.C | 61 +++++++++++++++++++++++++++++++++++ include/demangle.h | 2 ++ libiberty/cp-demangle.c | 39 ++++++++++++++++++---- libiberty/testsuite/demangle-expected | 9 ++++++ 5 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/mangle79.C diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc index 7d8f443f85c..a04bc584586 100644 --- a/gcc/cp/mangle.cc +++ b/gcc/cp/mangle.cc @@ -1247,6 +1247,9 @@ write_nested_name (const tree decl) write_char ('R'); } } + else if (DECL_DECLARES_FUNCTION_P (decl) + && DECL_XOBJ_MEMBER_FUNCTION_P (decl)) + write_char ('H'); /* Is this a template instance? */ if (tree info = maybe_template_info (decl)) diff --git a/gcc/testsuite/g++.dg/abi/mangle79.C b/gcc/testsuite/g++.dg/abi/mangle79.C new file mode 100644 index 00000000000..99ae822201e --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/mangle79.C @@ -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 + static void bar (S, T); + template + 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 +void +S::bar (S, T) +{ +} + +template +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_" } } diff --git a/include/demangle.h b/include/demangle.h index 6a03f4f4f93..49b84d4de88 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -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. */ diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index dee36173896..fc2cf64e6e0 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -581,6 +581,7 @@ static char *d_demangle (const char *, int, size_t *); 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, int indent) 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) /* ::= N [] [] E ::= N [] [] E + ::= N H E + ::= N H 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_info *dpi, 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, int options, 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_info *dpi, int options, { 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_info *dpi, int options, 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_info *dpi, int options, 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)); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 0997e96ea43..0f7b97a6d0a 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -1700,3 +1700,12 @@ void f() requires C # requires after () _Z1fIiEvvQ1CIT_E void f() requires C + +_ZNH1S3fooES_ +S::foo(this S) + +_ZNH1S3barILi5EiEEvS_T0_ +void S::bar<5, int>(this S, int) + +_ZNH1S3bazERKS_ +S::baz(this S const&) -- 2.11.4.GIT