diff options
author | Jason Merrill <jason@redhat.com> | 2023-08-17 11:36:23 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2023-08-22 14:34:53 -0400 |
commit | 810bcc00156cefce7ad40fc9d8de6e43c3a04450 (patch) | |
tree | fffaeb2e3b51bd3ee96f9265bc039a056c474d23 /libiberty | |
parent | 3571cc93511b39f7a403fe5eab0e316cd7e86220 (diff) | |
download | gcc-810bcc00156cefce7ad40fc9d8de6e43c3a04450.zip gcc-810bcc00156cefce7ad40fc9d8de6e43c3a04450.tar.gz gcc-810bcc00156cefce7ad40fc9d8de6e43c3a04450.tar.bz2 |
c++: constrained hidden friends [PR109751]
r13-4035 avoided a problem with overloading of constrained hidden friends by
checking satisfaction, but checking satisfaction early is inconsistent with
the usual late checking and can lead to hard errors, so let's not do that
after all.
We were wrongly treating the different instantiations of the same friend
template as the same function because maybe_substitute_reqs_for was failing
to actually substitute in the case of a non-template friend. But we don't
actually need to do the substitution anyway, because [temp.friend] says that
such a friend can't be the same as any other declaration.
After fixing that, instead of a redefinition error we got an ambiguous
overload error, fixed by allowing constrained hidden friends to coexist
until overload resolution, at which point they probably won't be in the same
ADL overload set anyway.
And we avoid mangling collisions by following the proposed mangling for
these friends as a member function with an extra 'F' before the name. I
demangle this by just adding [friend] to the name of the function because
it's not feasible to reconstruct the actual scope of the function since the
mangling ABI doesn't distinguish between class and namespace scopes.
PR c++/109751
gcc/cp/ChangeLog:
* cp-tree.h (member_like_constrained_friend_p): Declare.
* decl.cc (member_like_constrained_friend_p): New.
(function_requirements_equivalent_p): Check it.
(duplicate_decls): Check it.
(grokfndecl): Check friend template constraints.
* mangle.cc (decl_mangling_context): Check it.
(write_unqualified_name): Check it.
* pt.cc (uses_outer_template_parms_in_constraints): Fix for friends.
(tsubst_friend_function): Don't check satisfaction.
include/ChangeLog:
* demangle.h (enum demangle_component_type): Add
DEMANGLE_COMPONENT_FRIEND.
libiberty/ChangeLog:
* cp-demangle.c (d_make_comp): Handle DEMANGLE_COMPONENT_FRIEND.
(d_count_templates_scopes): Likewise.
(d_print_comp_inner): Likewise.
(d_unqualified_name): Handle member-like friend mangling.
* testsuite/demangle-expected: Add test.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-friend11.C: Now works. Add template.
* g++.dg/cpp2a/concepts-friend15.C: New test.
Diffstat (limited to 'libiberty')
-rw-r--r-- | libiberty/cp-demangle.c | 17 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 3 |
2 files changed, 20 insertions, 0 deletions
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 3bd303a..2ce984f 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1036,6 +1036,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM: case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM: case DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM: + case DEMANGLE_COMPONENT_FRIEND: if (left == NULL) return NULL; break; @@ -1681,6 +1682,7 @@ d_maybe_module_name (struct d_info *di, struct demangle_component **name) /* <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>] ::= [<module-name>] <ctor-dtor-name> [<abi-tags>] ::= [<module-name>] <source-name> [<abi-tags>] + ::= [<module-name>] F <source-name> [<abi-tags>] ::= [<module-name>] <local-source-name> [<abi-tags>] ::= [<module-name>] DC <source-name>+ E [<abi-tags>] <local-source-name> ::= L <source-name> <discriminator> [<abi-tags>] @@ -1692,11 +1694,18 @@ d_unqualified_name (struct d_info *di, struct demangle_component *scope, { struct demangle_component *ret; char peek; + int member_like_friend = 0; if (!d_maybe_module_name (di, &module)) return NULL; peek = d_peek_char (di); + if (peek == 'F') + { + member_like_friend = 1; + d_advance (di, 1); + peek = d_peek_char (di); + } if (IS_DIGIT (peek)) ret = d_source_name (di); else if (IS_LOWER (peek)) @@ -1773,6 +1782,8 @@ d_unqualified_name (struct d_info *di, struct demangle_component *scope, ret = d_make_comp (di, DEMANGLE_COMPONENT_MODULE_ENTITY, ret, module); if (d_peek_char (di) == 'B') ret = d_abi_tags (di, ret); + if (member_like_friend) + ret = d_make_comp (di, DEMANGLE_COMPONENT_FRIEND, ret, NULL); if (scope) ret = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, scope, ret); @@ -4459,6 +4470,7 @@ d_count_templates_scopes (struct d_print_info *dpi, case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: case DEMANGLE_COMPONENT_MODULE_ENTITY: + case DEMANGLE_COMPONENT_FRIEND: d_count_templates_scopes (dpi, d_left (dc)); break; @@ -6197,6 +6209,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_append_char (dpi, ']'); return; + case DEMANGLE_COMPONENT_FRIEND: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, "[friend]"); + return; + case DEMANGLE_COMPONENT_TEMPLATE_HEAD: { d_append_char (dpi, '<'); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 0acd2d6..01ca222 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -1689,3 +1689,6 @@ X::operator Z<int><int>()::y _ZZN1XIfEcv1ZIT_EIiEEvE1y X<float>::operator Z<int><int>()::y + +_ZN1SILi1EEF3barIiEEiR4Base +int S<1>::bar[friend]<int>(Base&) |