Description
Bugzilla Link | 26462 |
Version | unspecified |
OS | Linux |
CC | @majnemer,@hfinkel,@kbeyls,@zygoloid,@rjmccall,@lenary,@tstellar,@jwakely |
Extended Description
Clang and GCC have incompatible ABIs for _Atomic
, on non-power-of-2-sized types.
Simple demonstration of the difference:
struct A3 { char val[3]; };
_Atomic struct A3 a3;
// GCC:
_Static_assert(sizeof(a3) == 3, "");
_Static_assert(_Alignof(a3) == 1, "");
// Clang:
_Static_assert(sizeof(a3) == 4, "");
_Static_assert(_Alignof(a3) == 4, "");
GCC's logic for _Atomic
is: For types which have a size of exactly 1, 2, 4, 8, or 16 bytes, increase the alignment to be at least the size. Never change the size of the type.
libstdc++'s std::atomic
uses the same logic as GCC, but it's implemented inline in the header, as GCC doesn't support C11 atomics in C++ mode. Thus, libstdc++ under clang also uses GCC's rule.
Clang has the following rule: if the size of a type is less than a target-specific variable MaxAtomicPromoteWidth
(0, 4, 8, or 16 bytes on current targets), round the size up to the next power of two, and SET the alignment to the size.
libc++'s std::atomic
uses clang's C11 atomics support (which clang supports as an extension in C++ mode), and thus gets the same behavior...but only when built with clang. When libc++ is built with GCC, it uses an alternative implementation which doesn't ever increase the alignment/size.
So, the current situation:
- C11
_Atomic
is incompatible between Clang and GCC. - libstdc++'s
std::atomic
is compatible between Clang and GCC. - libc++'s
std::atomic
is incompatible between Clang and GCC.
Furthermore, I believe C11 and C++ atomics are intended to be compatible with eachother. And that's not true with clang and libstdc++, nor with gcc and libc++.