On Wed, Aug 23, 2023 at 04:23:00PM -0400, Jason Merrill wrote: > I'd be surprised if this would affect any real code, but I suppose so. In > any case I'd like to fix this at the same time as the local statics, to > avoid changing their mangled name twice.
Ok. Running now into a problem with abi tags, because cp_maybe_mangle_decomp is called before the type of the structured binding is finalized (sequence is cp_maybe_mangle_decomp; cp_finish_decl; cp_finish_decomp), I vaguely remember the reason was to have the name already mangled by cp_finish_decl time, so that it can add it into varpool etc.. Will see if I can e.g. pass the initializer expression to cp_maybe_mangle_decomp and figure out the tags from that. > > @@ -9049,6 +9050,25 @@ cp_maybe_mangle_decomp (tree decl, tree > > tree d = first; > > for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) > > v[count - i - 1] = d; > > + if (DECL_FUNCTION_SCOPE_P (decl)) > > + { > > + size_t sz = 3; > > + for (unsigned int i = 0; i < count; ++i) > > + sz += IDENTIFIER_LENGTH (DECL_NAME (v[i])) + 1; > > + char *name = XALLOCAVEC (char, sz); > > + name[0] = 'D'; > > + name[1] = 'C'; > > + char *p = name + 2; > > + for (unsigned int i = 0; i < count; ++i) > > + { > > + size_t len = IDENTIFIER_LENGTH (DECL_NAME (v[i])); > > + *p++ = ' '; > > + memcpy (p, IDENTIFIER_POINTER (DECL_NAME (v[i])), len); > > + p += len; > > + } > > + *p = '\0'; > > + determine_local_discriminator (decl, get_identifier (name)); > > + } > > Maybe do this in mangle_decomp, based on the actual mangling in process > instead of this pseudo-mangling? Not sure that is possible, for 2 reasons: 1) determine_local_discriminator otherwise works on DECL_NAME, not mangled names, so if one uses (albeit implementation reserved) _ZZN1N3fooI1TB3bazEEivEDC1h1iEB6foobar and similar identifiers, they could clash with the counting of the structured bindings 2) seems the local discriminator counting shouldn't take into account details like abi tags, e.g. if I have: struct [[gnu::abi_tag ("foobar")]] S { int a; }; namespace N { template <typename T> inline int foo () { static int h = 42; int r = ++h; { static S h = { 42 }; r += ++h.a; } { static int h = 42; r += ++h; } { static S h = { 42 }; r += ++h.a; } return r; } } int (*p) () = N::foo<int>; then both GCC and Clang mangle these as _ZZN1N3fooIiEEivE1h _ZZN1N3fooIiEEivE1hB6foobar_0 _ZZN1N3fooIiEEivE1h_1 _ZZN1N3fooIiEEivE1hB6foobar_2 so whether abi tags appear in the mangled name or not shouldn't result in separate buckets for counting. > > > @@ -4564,6 +4519,13 @@ write_guarded_var_name (const tree varia > > /* 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")) > > Maybe add a startswith overload that takes an identifier? Ok. > > @@ -4630,7 +4592,10 @@ mangle_ref_init_variable (const tree var > > start_mangling (variable); > > write_string ("_ZGR"); > > check_abi_tags (variable); > > - write_name (variable, /*ignore_local_scope=*/0); > > + if (DECL_DECOMPOSITION_P (variable)) > > + write_guarded_var_name (variable); > > + else > > + write_name (variable, /*ignore_local_scope=*/0); > > Why not use write_guarded_name unconditionally? Ok. Jakub