Does clang now emit [abi:cxx11] unconditionally when used with libstdc++?

Or do we have an option to select whether clang++ compiles for the old or the new abi?

Thanks, M.

Hi Maria,

Are you referring to “__attribute ((abi_tag)” support? If yes, it is enabled by default, no need for special options.

You can use libstdc++ without additional options as well.

Yours,
Andrey

Hmm. Yes, I'm refering to this gcc abi tag stuff. My question actually was how to disable this support in clang. With gcc the default (old/new abi) ist a build-time option. And one can also switch at compile time with a macro: -D_GLIBCXX_USE_CXX11_ABI=0/1.

Existing LTS distributions like RHEL stick to the old abi, of course, when they offer newer gcc's as an add-on. Otherwise, you could not link to any C++ system libraries.

So, is it correct that clang-3.9.0 unconditionally compiles for the new abi? That gcc 4.x.y is no longer usable and that you must have gcc 5+ if you want to use libstdc++?

That would be real bad.

Thanks,
M.

Hi Maria,

Are you referring to "__attribute ((abi_tag)" support? If yes, it is enabled by default, no need for special options.

You can use libstdc++ without additional options as well.

Yours,
Andrey

Or do we have an option to select whether clang++ compiles for the old or the new abi?

+Renato who understands this stuff (I don't).

Oh bother! Adding Dmitry, as he wrote the code [1].

I was under the impression that, if you didn't use the tag, nothing
would have changed.

We don't have many compile-time options like GCC, so this would have
to be a run-time option, if needed.

cheers,
--renato

[1] https://reviews.llvm.org/D18035 and https://reviews.llvm.org/D17567

As I understand, -D_GLIBCXX_USE_CXX11_ABI is a library flag, not compiler one, so clang should work with libstdc++ exactly as gcc5+ do. See http://developers.redhat.com/blog/2015/02/05/gcc5-and-the-c11-abi/ for details.

Yours,
Andrey

To clarify, this is obviously a compiler flag, but the macro is consumed by the library (not compiler) and doesn’t affect how gcc/clang work. Thus, if you want old mangling, just pass this flag either to gcc or clang.

Yours,
Andrey

I did a little experiment. I’ve built 3.9.0rc1 with gcc-4.9.2 and then let this 3.9.0rc1 rebuild itself (using again headers and libstdc++ from gcc-4.9.2).

$ nm -C libLLVMCore.a | grep cxx11
0000000000000000 W std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::lessstd::string, std::allocator<std::pair<std::string const, std::string> > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<std::string const, std::string> >)
0000000000000000 W std::_Rb_tree<std::string, std::pair<std::string const, std::string>, std::_Select1st<std::pair<std::string const, std::string> >, std::lessstd::string, std::allocator<std::pair<std::string const, std::string> > >::erase[abi:cxx11](std::_Rb_tree_const_iterator<std::pair<std::string const, std::string> >)

That’s two times [abi:cxx11]. But libstdc++ from gcc-4.9.2 doesn’t use abi tags, does it?

(The build completes anyway and all tests succeed!)

M.

To clarify, this is obviously a compiler flag, but the macro is consumed by the library (not compiler) and doesn’t affect how gcc/clang work. Thus, if you want old mangling, just pass this flag either to gcc or clang.

Yours,
Andrey

I did a little experiment. I've built 3.9.0rc1 with gcc-4.9.2 and then let
this 3.9.0rc1 rebuild itself (using again headers and libstdc++ from
gcc-4.9.2).

$ nm -C libLLVMCore.a | grep cxx11
0000000000000000 W std::_Rb_tree<std::string, std::pair<std::string const,
std::string>, std::_Select1st<std::pair<std::string const, std::string>
>, std::less<std::string>, std::allocator<std::pair<std::string const,
std::string> > >::erase[abi:cxx11](std::_Rb_tree_iterator<std::pair<std::string
const, std::string> >)
0000000000000000 W std::_Rb_tree<std::string, std::pair<std::string const,
std::string>, std::_Select1st<std::pair<std::string const, std::string>
>, std::less<std::string>, std::allocator<std::pair<std::string const,
std::string> > >::erase[abi:cxx11](std::_Rb_tree_const_iterator<std::pair<std::string
const, std::string> >)

That's two times [abi:cxx11]. But libstdc++ from gcc-4.9.2 doesn't use
abi tags, does it?

*shrug* If an ABI tag appears in a mangling, then the code fed to Clang
contained an __attribute__((abi_tag)). There's no other way for it to get
there. You could try preprocessing the relevant source file (with -E) and
see if the abi_tag attribute appears somewhere in the output if you're
curious how it's getting into your build.

(How sure are you that Clang is using libstdc++ 4.9.2 and not a later
version?)

(How sure are you that Clang is using libstdc++ 4.9.2 and not a later version?)

$ clang -v
...
Selected GCC installation: /opt/rh/devtoolset-3/root/usr/lib/gcc/x86_64-redhat-linux/4.9.2
...

But actually, there were abi tags already in 4.9.2, e.g.

https://github.com/gcc-mirror/gcc/blob/gcc-4_9_2-release/libstdc++-v3/include/bits/stl_map.h

Search for _GLIBCXX_ABI_TAG_CXX11 which is __attribute ((__abi_tag__ ("cxx11"))).

But then gcc-4.9.2 doesn't emit any, while now clang-3.9.0 does!

I'd risk say this is a bug in GCC. Or at least a pretty ugly
implementation of something that should be simple.

We can't be compatible with all versions of GCC on what attributes
they support and the compile-time flags that they use. This just
doesn't scale.

In a way, if you don't want ABI tags, use Clang 3.8 or before. If you
do, use Clang 3.9 or after.

I'm not sure there's a better way of doing this and creating a
compile-time flag just to imitate GCC seems like the wrong way to go,
IMO.

cheers,
--renato

> But actually, there were abi tags already in 4.9.2, e.g.
>
> But then gcc-4.9.2 doesn't emit any, while now clang-3.9.0 does!

I'd risk say this is a bug in GCC. Or at least a pretty ugly
implementation of something that should be simple.

If it's only applied to an inline function, and that function did in fact
take an ABI break in libstdc++ 4.9.2, then this seems unproblematic. If
anything, our results will be marginally better than GCC 4.9.2's, because
we'll do the right thing when mixing libstdc++ 4.9.2 and an earlier
version. It looks like there is nothing to fix here.

I agree that it looks like a GCC bug that abi_tags are ignored in GCC 4.9.2. Anyway, if at some point we will want to implement it in Clang, I think right approach is to implement -fabi_version flags and, if specified ABI version is below GCC5, don’t emit abi_tags in mangling.

I don’t think it’s a bug if they only applied abi_tag to entities like this inline function that will be instantiated into every object file where they’re used and whose address is irrelevant. It’s essentially inconsequential whether you do the abi_tag mangling or not here, unless you’re actually mixing different ABI versions for the same type in the same program. What this does mean is that you can’t mix code compiled with libstdc++4.9 with dual-ABI code from GCC 5 onwards, but that was already the case in some corner cases due to other ABI breaks libstdc++ accidentally made prior to 5.0.

My two cents: clang already knows the exact version of gcc from which it borrows libstdc++, because it sorts available gcc's by version number to pick the one with the highest number. Then:

If major version < 5: never emit abi tags.

If major version >=5: emit abi tags if requested with __attribute ((__abi_tag__ ("..."))).

This on the assumption that there is something to fix. Richard said there isn't. I wouldn't know.

M.

I agree that it looks like a GCC bug that abi_tags are ignored in GCC 4.9.2. Anyway, if at some point we will want to implement it in Clang, I think right approach is to implement -fabi_version flags and, if specified ABI version is below GCC5, don't emit abi_tags in mangling.

If major version < 5: never emit abi tags.
If major version >=5: emit abi tags if requested with __attribute ((__abi_tag__ ("..."))).

I don't think that's appropriate, as that would change the behaviour
based on the library's version, not its source code.

If the source has abi tags, and we support abi tags, we *must* emit
abi tags in the mangling.

This on the assumption that there is something to fix. Richard said there isn't. I wouldn't know.

The new c++11 functions were added to support the new abi, so old abi
library consumers would never hit them, making this "not a problem".

If library consumers do hit them, than they're aware of the problem
and intend to, in which case, exposing it is only logical.

This looks like a behavioural problem, not a compiler problem, so
fixing it in the compiler is a bad move.

If you don't want abi tags support, stick to Clang 3.8.

If you want Clang 3.9+ without abi tag support, revert the two patches
and use that. Of course, any bug in that toolchain would have to be
reproduced in an upstream release to be considered.

cheers,
--renato

If major version < 5: never emit abi tags.
If major version >=5: emit abi tags if requested with __attribute ((__abi_tag__ ("..."))).

I don't think that's appropriate, as that would change the behaviour
based on the library's version, not its source code.

That's precisely the point: every version of gcc comes with it's own copy of libstdc++. For compile-time linking you are supposed to use exactly this copy and nothing else. Now, if clang wants to use libstdc++ from gcc-4.9.2, it has to behave like gcc-4.9.2. And that means not emitting abi tags, even if they are in the code. Doing what gcc-4.9.2 does is the well tested and the de facto right behaviour when using libstdc++ from 4.9.2, even if you think it's buggy.

And the fact that nobody has ever seen gcc emitting abi tags before gcc5 translates to the simple logic outlined above.

If you don't want abi tags support, stick to Clang 3.8.

Not a very helpful suggestion, but I got it.

M.

Except, as Richard mentioned, it's not actually a problem that needs to be
fixed. That the mangled names of the inline functions are different is
effectively irrelevant.