aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/mangle.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-09-01 15:07:48 +0200
committerJakub Jelinek <jakub@redhat.com>2023-09-01 15:07:48 +0200
commitcd37325b8d500bf4021692620686572d5ffb0868 (patch)
tree99ef66edf9cc84d5818ecb726df88874fa5dc463 /gcc/cp/mangle.cc
parentc2d3211d580369b75200fbdd7b854d30460e0aba (diff)
downloadgcc-cd37325b8d500bf4021692620686572d5ffb0868.zip
gcc-cd37325b8d500bf4021692620686572d5ffb0868.tar.gz
gcc-cd37325b8d500bf4021692620686572d5ffb0868.tar.bz2
c++: Fix up mangling of function/block scope static structured bindings [PR111069]
As can be seen on the testcase, we weren't correctly mangling static/thread_local structured bindings (C++20 feature) at function/block scope. The following patch fixes that by using what write_local_name does for those cases (note, structured binding mandling doesn't use the standard path because it needs to pass a list of all the identifiers in the structured binding to the mangling). In addition to that it fixes mangling of various helpers which use write_guarded_name (_ZGV*, _ZTH*, _ZTW*) and kills find_decomp_unqualified_name which for the local names would be too hard to implement and uses write_guarded_name for structured binding related _ZGR* names as well. All the mangled names on the first testcase match now clang++ and my expectations. Because the old mangled names were plain wrong (they mangled the same as structured binding at global scope and resulted in assembly errors if there was more than one static structured binding with the same identifiers in the same (or another) function, I think we don't need to play with another mangling ABI level which turns on/off the old broken way. In addition to that the patch starts to emit abi-tags into the mangle_decomp produced names when needed and emits a -Wabi warning for that as well. To make that work, I had to move cp_maybe_mangle_decomp calls from before cp_finish_decl into a middle of cp_finish_decl after type is deduced and maybe_commonize_var (which also had to be changed not to ignore structured bindings) is called but before anything might need a mangled name for the decl, so a new cp_decomp structure is passed to cp_finish_decl; various other structured binding related functions have been changed to pass pointer to that around instead of passing a tree and unsigned int separately. On decomp9.C, there is a _ZZ3barI1TB3quxEivEDC1o1pEB3qux (g++) vs. _ZZ3barI1TB3quxEivEDC1o1pE (clang++) mangling difference, but that seems to be a clang++ bug and happens also with normal static block vars, doesn't need structured bindings. 2023-09-01 Jakub Jelinek <jakub@redhat.com> PR c++/111069 gcc/ * common.opt (fabi-version=): Document version 19. * doc/invoke.texi (-fabi-version=): Likewise. gcc/c-family/ * c-opts.cc (c_common_post_options): Change latest_abi_version to 19. gcc/cp/ * cp-tree.h (determine_local_discriminator): Add NAME argument with NULL_TREE default. (struct cp_decomp): New type. (cp_finish_decl): Add DECOMP argument defaulted to nullptr. (cp_maybe_mangle_decomp): Remove declaration. (cp_finish_decomp): Add cp_decomp * argument, remove tree and unsigned args. (cp_convert_range_for): Likewise. * decl.cc (determine_local_discriminator): Add NAME argument, use it if non-NULL, otherwise compute it the old way. (maybe_commonize_var): Don't return early for structured bindings. (cp_finish_decl): Add DECOMP argument, if non-NULL, call cp_maybe_mangle_decomp. (cp_maybe_mangle_decomp): Make it static with a forward declaration. Call determine_local_discriminator. Replace FIRST and COUNT arguments with DECOMP argument. (cp_finish_decomp): Replace FIRST and COUNT arguments with DECOMP argument. * mangle.cc (find_decomp_unqualified_name): Remove. (write_unqualified_name): Don't call find_decomp_unqualified_name. (mangle_decomp): Handle mangling of static function/block scope structured bindings. Don't call decl_mangling_context twice. Call check_abi_tags, call write_abi_tags for abi version >= 19 and emit -Wabi warnings if needed. (write_guarded_var_name): Handle structured bindings. (mangle_ref_init_variable): Use write_guarded_var_name. * parser.cc (cp_parser_range_for): Adjust do_range_for_auto_deduction and cp_convert_range_for callers. (do_range_for_auto_deduction): Replace DECOMP_FIRST_NAME and DECOMP_CNT arguments with DECOMP. Adjust cp_finish_decomp caller. (cp_convert_range_for): Replace DECOMP_FIRST_NAME and DECOMP_CNT arguments with DECOMP. Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. (cp_parser_decomposition_declaration): Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. (cp_convert_omp_range_for): Adjust do_range_for_auto_deduction and cp_finish_decomp callers. (cp_finish_omp_range_for): Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. * pt.cc (tsubst_omp_for_iterator): Adjust tsubst_decomp_names caller. (tsubst_decomp_names): Replace FIRST and CNT arguments with DECOMP. (tsubst_expr): Don't call cp_maybe_mangle_decomp, adjust tsubst_decomp_names, cp_finish_decl, cp_finish_decomp and cp_convert_range_for callers. gcc/testsuite/ * g++.dg/cpp2a/decomp8.C: New test. * g++.dg/cpp2a/decomp9.C: New test. * g++.dg/abi/macro0.C: Expect __GXX_ABI_VERSION 1019 rather than 1018.
Diffstat (limited to 'gcc/cp/mangle.cc')
-rw-r--r--gcc/cp/mangle.cc122
1 files changed, 64 insertions, 58 deletions
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index bb0e9d3..d88c779 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1347,51 +1347,6 @@ write_template_prefix (const tree node)
add_substitution (substitution);
}
-/* As the list of identifiers for the structured binding declaration
- DECL is likely gone, try to recover the DC <source-name>+ E portion
- from its mangled name. Return pointer to the DC and set len to
- the length up to and including the terminating E. On failure
- return NULL. */
-
-static const char *
-find_decomp_unqualified_name (tree decl, size_t *len)
-{
- const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl));
- bool nested = false;
- if (!startswith (p, "_Z"))
- return NULL;
- p += 2;
- if (startswith (p, "St"))
- p += 2;
- else if (*p == 'N')
- {
- nested = true;
- ++p;
- while (ISDIGIT (p[0]))
- {
- char *e;
- long num = strtol (p, &e, 10);
- if (num >= 1 && num < end - e)
- p = e + num;
- else
- break;
- }
- }
- if (!startswith (p, "DC"))
- return NULL;
- if (nested)
- {
- if (end[-1] != 'E')
- return NULL;
- --end;
- }
- if (end[-1] != 'E')
- return NULL;
- *len = end - p;
- return p;
-}
-
/* "For the purposes of mangling, the name of an anonymous union is considered
to be the name of the first named data member found by a pre-order,
depth-first, declaration-order walk of the data members of the anonymous
@@ -1465,17 +1420,7 @@ write_unqualified_name (tree decl)
{
found = true;
gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
- const char *decomp_str = NULL;
- size_t decomp_len = 0;
- if (VAR_P (decl)
- && DECL_DECOMPOSITION_P (decl)
- && DECL_NAME (decl) == NULL_TREE
- && DECL_NAMESPACE_SCOPE_P (decl))
- decomp_str = find_decomp_unqualified_name (decl, &decomp_len);
- if (decomp_str)
- write_chars (decomp_str, decomp_len);
- else
- write_source_name (DECL_ASSEMBLER_NAME (decl));
+ write_source_name (DECL_ASSEMBLER_NAME (decl));
}
else if (DECL_DECLARES_FUNCTION_P (decl))
{
@@ -4373,6 +4318,7 @@ mangle_decomp (const tree decl, vec<tree> &decls)
location_t saved_loc = input_location;
input_location = DECL_SOURCE_LOCATION (decl);
+ check_abi_tags (decl);
start_mangling (decl);
write_string ("_Z");
@@ -4380,13 +4326,21 @@ mangle_decomp (const tree decl, vec<tree> &decls)
gcc_assert (context != NULL_TREE);
bool nested = false;
+ bool local = false;
if (DECL_NAMESPACE_STD_P (context))
write_string ("St");
+ else if (TREE_CODE (context) == FUNCTION_DECL)
+ {
+ local = true;
+ write_char ('Z');
+ write_encoding (context);
+ write_char ('E');
+ }
else if (context != global_namespace)
{
nested = true;
write_char ('N');
- write_prefix (decl_mangling_context (decl));
+ write_prefix (context);
}
write_string ("DC");
@@ -4396,8 +4350,22 @@ mangle_decomp (const tree decl, vec<tree> &decls)
write_unqualified_name (d);
write_char ('E');
+ if (tree tags = get_abi_tags (decl))
+ {
+ /* We didn't emit ABI tags for structured bindings before ABI 19. */
+ if (!G.need_abi_warning
+ && TREE_PUBLIC (decl)
+ && abi_warn_or_compat_version_crosses (19))
+ G.need_abi_warning = 1;
+
+ if (abi_version_at_least (19))
+ write_abi_tags (tags);
+ }
+
if (nested)
write_char ('E');
+ else if (local && DECL_DISCRIMINATOR_P (decl))
+ write_discriminator (discriminator_for_local_entity (decl));
tree id = finish_mangling_get_identifier ();
if (DEBUG_MANGLE)
@@ -4405,6 +4373,37 @@ mangle_decomp (const tree decl, vec<tree> &decls)
IDENTIFIER_POINTER (id));
input_location = saved_loc;
+
+ if (warn_abi && G.need_abi_warning)
+ {
+ const char fabi_version[] = "-fabi-version";
+ tree id2 = id;
+ int save_ver = flag_abi_version;
+
+ if (flag_abi_version != warn_abi_version)
+ {
+ flag_abi_version = warn_abi_version;
+ id2 = mangle_decomp (decl, decls);
+ flag_abi_version = save_ver;
+ }
+
+ if (id2 == id)
+ /* OK. */;
+ else if (warn_abi_version != 0
+ && abi_version_at_least (warn_abi_version))
+ warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
+ "the mangled name of %qD changed between "
+ "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+ G.entity, fabi_version, warn_abi_version, id2,
+ fabi_version, save_ver, id);
+ else
+ warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi,
+ "the mangled name of %qD changes between "
+ "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)",
+ G.entity, fabi_version, save_ver, id,
+ fabi_version, warn_abi_version, id2);
+ }
+
return id;
}
@@ -4574,6 +4573,13 @@ write_guarded_var_name (const tree variable)
/* The name of a guard variable for a reference temporary should refer
to the reference, not the temporary. */
write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
+ else if (DECL_DECOMPOSITION_P (variable)
+ && DECL_NAME (variable) == NULL_TREE
+ && startswith (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)),
+ "_Z"))
+ /* The name of a guard variable for a structured binding needs special
+ casing. */
+ write_string (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)) + 2);
else
write_name (variable, /*ignore_local_scope=*/0);
}
@@ -4640,7 +4646,7 @@ mangle_ref_init_variable (const tree variable)
start_mangling (variable);
write_string ("_ZGR");
check_abi_tags (variable);
- write_name (variable, /*ignore_local_scope=*/0);
+ write_guarded_var_name (variable);
/* Avoid name clashes with aggregate initialization of multiple
references at once. */
write_compact_number (current_ref_temp_count++);