#include <type_traits> static_assert(sizeof(std::aligned_storage<4>::type) == 4, ""); so.cc: In function ‘int main()’: so.cc:5:3: error: static assertion failed: static_assert(sizeof(std::aligned_storage<4>::type) == 4, ""); ^ I think this is conforming, but it would be more useful if it passed. We use the maximum alignment supported for any type, where we should use the maximum alignment supported for types less than 4 bytes
If we're going to fix this we should do it now, before the C++11 ABI is declared stable.
The problem is the default value of the _Align parameter, which comes from alignof(__aligned_storage_msa<_Len>::__type) which is always the maximum alignment: template<size_t _Len> struct __aligned_storage_msa { union __type { unsigned char __data[_Len]; struct __attribute__((__aligned__)) { } __align; }; }; That effectively ignores _Len and will always have 16-byte alignment, which means sizeof(aligned_storage<N>) is always at least 16 bytes. Should the attribute be using __aligned__(_Len) or does that do the wrong thing in some cases?
P.S. this isn't an urgent problem for the library, as we don't use aligned_storage<N> internally, we always use __aligned_buffer<T> which specifies the alignment explicitly rather than relying on the 16-byte default.
Hi Jon. Frankly Are you 100% sure (in terms of middle-end/back-end details) that the maximum alignment supported for a type of less than 4 bytes is 4? In that case, your proposal of using __aligned__((_Len)) certainly makes sense. I wasn't sure at the time and picked a "safe" choice, probably should have asked...
GCC 5.1 has been released.
(In reply to Paolo Carlini from comment #4) > Hi Jon. Frankly Are you 100% sure (in terms of middle-end/back-end details) > that the maximum alignment supported for a type of less than 4 bytes is 4? It's a good question, I'm definitely not 100% sure.
GCC 5.2 is being released, adjusting target milestone to 5.3.
GCC 5.3 is being released, adjusting target milestone.
I don't think it's necessary to change anything.
Could we revisit this issue? Libstdc++'s behavior here seems to be "conforming but sadistic," in that it gratuitously breaks the ABI of user/library code that assumes aligned_storage_t<Cap> is appropriately aligned for objects of size Cap. For example, SG14's "stdext::inplace_function" was recently declared as follows: template< typename Signature, size_t Capacity = detail::InplaceFunctionDefaultCapacity, size_t Alignment = std::alignment_of<std::aligned_storage_t<Capacity>>::value > class inplace_function; This works great on Clang/libc++, but gives a different ABI on GCC/libstdc++ because on libstdc++ the default alignment is "always 16 bytes" instead of "appropriately aligned for Capacity". using IPF = stdext::inplace_function<void(), 8>; if (sizeof(IPF) == 16) { puts("MSVC and libc++ pack aligned_storage_t appropriately!"); } else if (sizeof(IPF) == 32) { puts("libstdc++ breaks ABI by adding lots of padding for no reason!"); } I'm not 100% sure yet, but it *seems* like the only workaround is for all library writers to implement their own version of aligned_storage_t; the standard version is not portable to platforms that use libstdc++. Here is a conforming version of "aligned_storage", checked into the SG14 repo as a workaround for the ongoing libstdc++ issue. https://github.com/WG21-SG14/SG14/commit/98baf1aeab
That's not an ABI break. Changing it now would be an ABI break.
Patch posted to fix this for the unstable ABI only: https://gcc.gnu.org/pipermail/gcc-patches/2024-October/664287.html
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:6ce1df379a64439ea429b6c5834e9f853d520112 commit r15-4207-g6ce1df379a64439ea429b6c5834e9f853d520112 Author: Jonathan Wakely <jwakely@redhat.com> Date: Thu Sep 26 16:42:27 2024 +0100 libstdc++: Simplify std::aligned_storage and fix for versioned namespace [PR61458] This simplifies the implementation of std::aligned_storage. For the unstable ABI it also fixes the bug where its size is too large when the default alignment is used. We can't fix that for the stable ABI though, so just add a comment about the bug. libstdc++-v3/ChangeLog: PR libstdc++/61458 * doc/doxygen/user.cfg.in (GENERATE_BUGLIST): Set to NO. * include/std/type_traits (__aligned_storage_msa): Remove. (__aligned_storage_max_align_t): New struct. (__aligned_storage_default_alignment): New function. (aligned_storage): Use __aligned_storage_default_alignment for default alignment. Replace union with a struct containing an aligned buffer. Improve Doxygen comment. (aligned_storage_t): Use __aligned_storage_default_alignment for default alignment.