On 8/28/23 09:58, Jakub Jelinek wrote:
Hi!

On Thu, Aug 24, 2023 at 06:39:10PM +0200, Jakub Jelinek via Gcc-patches wrote:
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

I guess, but those names are reserved so that we don't need to worry about that.

2) seems the local discriminator counting shouldn't take into account
    details like abi tags, e.g. if I have:

Right, you'd need to use the partial mangled name before the ABI tags, e.g. with get_identifier_with_length (obstack_base, obstack_object_size).

But the way you have it is fine too.

The following updated patch handles everything except it leaves for the
above 2 reasons the determination of local discriminator where it was.
I had to add a new (defaulted) argument to cp_finish_decl and do
cp_maybe_mangle_decomp from there, so that it is after e.g. auto type
deduction and maybe_commonize_var (which had to be changed as well) and
spots in cp_finish_decl where we need or might need mangled names already.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

There is one difference between g++ with this patch and clang++,
g++ uses
_ZZ3barI1TB3quxEivEDC1o1pEB3qux
while clang++ uses
_ZZ3barI1TB3quxEivEDC1o1pE
but from what I can see, such a difference is there also when just using
normal local decls:
struct [[gnu::abi_tag ("foobar")]] S { int i; };
struct [[gnu::abi_tag ("qux")]] T { int i; S j; int k; };

inline int
foo ()
{
   static S c;
   static T d;
   return ++c.i + ++d.i;
}

template <typename T>
inline int
bar ()
{
   static S c;
   static T d;
   return ++c.i + ++d.i;
}

int (*p) () = &foo;
int (*q) () = &bar<T>;
where both compilers mangle c in foo as:
_ZZ3foovE1cB6foobar
and d in there as
_ZZ3foovE1dB3qux
and similarly both compilers mangle c in bar as
_ZZ3barI1TB3quxEivE1cB6foobar
but g++ mangles d in bar as
_ZZ3barI1TB3quxEivE1dB3qux
while clang++ mangles it as just
_ZZ3barI1TB3quxEivE1d
No idea what is right or wrong according to Itanium mangling.

I think g++ is right.

This has to do with the ABI "If part of a declaration's type is not represented in the mangling, i.e. the type of a variable or a return type that is not represented in the mangling of a function, any ABI tags on that type (or components of a compound type) that are not also present in a mangled part of the type are applied to the name of the declaration."

Here the type of bar::d is not mangled, so the tags of T are applied to the name d.

I guess clang interpreted the above as "any ABI tags on that type that are not already present in the mangled name...", which would also be a reasonable rule but is not the actual rule in the ABI.

2023-08-28  Jakub Jelinek  <ja...@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.

Maybe cp_finish_decomp should take this as well? And tsubst_decomp_names, and various other functions with decomp_first_name/decomp_cnt parms?

+  if (tree tags = get_abi_tags (decl))
+    {
+      /* We didn't emit ABI tags for structured bindings before ABI 19.  */
+      if (!G.need_abi_warning
+          && abi_warn_or_compat_version_crosses (19))
+       G.need_abi_warning = 1;

In general we should probably only warn about mangling changes if TREE_PUBLIC (decl).

Jason

Reply via email to