Skip to content

Commit f5e687d

Browse files
philnik777ldionne
andauthored
[libc++] Fix ABI break introduced by switching to _LIBCPP_COMPRESSED_PAIR (llvm#154686)
LLVM 20 contained an ABI break that can result in the size of `std::unordered_{map,set,multimap,multiset}` and `std::deque` changing when used with an allocator type that is empty and contains a base class that is the same across rebound allocator instantiations (e.g. ``Allocator<int>`` and ``Allocator<char>`` are both empty and contain the same base class). In addition, the layout of a user-defined type that: - contains one of the following containers: `std::unordered_{map,set,multimap,multiset}`, `std::deque`, `std::map`, `std::set`, `std::multimap`, `std::multiset`, `std::list` or `std::vector`, and - passes an empty allocator, comparator or hasher type to that container, and - has a member of that same empty allocator, comparator or hasher type inside the enclosing struct, and - that member is either marked with `[[no_unique_address]]` or optimized out via the EBO (empty base optimization) technique saw its size increase from LLVM 19 to LLVM 20. This was caused by the usage of `[[no_unique_address]]` within some of libc++'s containers in a way that allowed subtle interactions with enclosing objects. This is fixed in LLVM 21 on Clang (returning to the LLVM 19 ABI), however that implies an ABI break from LLVM 20 to LLVM 21. Furthermore, fixing this causes a slight regression to constant evaluation support in `std::unique_ptr`. Specifically, constant evaluation will now fail when the deleter relies on being value-initialized for constant-evaluation admissibility. If a default-initialized deleter can be used during constant evaluation, or if the default constructor is non-trivial, the `unique_ptr` is not affected by this regression. In particular, this regression does not impact any `unique_ptr` using the default deleter. Note that there is currently no way to realistically fix this ABI break on GCC, therefore GCC will remain on the ABI introduced in LLVM 19. That also means that Clang and GCC will have a slightly different ABI for the small subset of types listed above until we are able to apply the same fix we did with Clang on GCC. We fix this regression by surrounding the members of the `_LIBCPP_COMPRESSED_PAIR` with an anonymous struct. This restricts the shifting of empty types to the front of the `_LIBCPP_COMPRESSED_PAIR` instead of throughout the surrounding object. This "frees up" the zero offset to contain another object of the same type, restoring the ability to perform EBO or to elide the storage for a type with `[[no_unique_address]]` in the enclosing (user-defined) struct. Fixes llvm#154146 Co-authored-by: Louis Dionne <[email protected]>
1 parent 6d29419 commit f5e687d

File tree

14 files changed

+189
-36
lines changed

14 files changed

+189
-36
lines changed

libcxx/docs/ReleaseNotes/21.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,21 @@ ABI Affecting Changes
148148
comparison between shared libraries, since all RTTI has the correct visibility now. There is no behaviour change on
149149
Clang.
150150

151+
- LLVM 20 contained an ABI break that can result in the size of ``std::unordered_{map,set,multimap,multiset}`` and ``std::deque`` changing when used with an allocator type that is empty and contains a base class that is the same across rebound allocator instantiations (e.g. ``Allocator<int>`` and ``Allocator<char>`` are both empty and contain the same base class).
152+
In addition, the layout of a user-defined type that:
153+
154+
- contains one of the following containers: ``std::unordered_{map,set,multimap,multiset}``, ``std::deque``, ``std::map``, ``std::set``, ``std::multimap``, ``std::multiset``, ``std::list`` or ``std::vector``, and
155+
- passes an empty allocator, comparator or hasher type to that container, and
156+
- has a member of that same empty allocator, comparator or hasher type inside the enclosing struct, and
157+
- that member is either marked with ``[[no_unique_address]]`` or optimized out via the EBO (empty base optimization) technique
158+
159+
saw its size increase from LLVM 19 to LLVM 20. This was caused by the usage of ``[[no_unique_address]]`` within some of libc++'s containers in a way that allowed subtle interactions with enclosing objects. This is fixed in LLVM 21 when using the Clang compiler (returning to the LLVM 19 ABI), however that implies an ABI break from LLVM 20 to LLVM 21.
160+
161+
Furthermore, fixing this causes a slight regression to constant evaluation support in ``std::unique_ptr``. Specifically, constant evaluation will now fail when the deleter relies on being value-initialized for constant-evaluation admissibility. If a default-initialized deleter can be used during constant evaluation, or if the default constructor is non-trivial, the ``unique_ptr`` is not affected by this regression. In particular, this regression does not impact any ``unique_ptr`` using the default deleter.
162+
163+
Note that there is currently no way to realistically fix this ABI break on GCC, therefore GCC will remain on the ABI introduced in LLVM 19. That also means that Clang and GCC will have a slightly different ABI for the small subset of types listed above until we are able to apply the same fix we did with Clang on GCC.
164+
165+
For more details see https://llvm.org/PR154146.
151166

152167
Build System Changes
153168
--------------------

libcxx/include/__memory/compressed_pair.h

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,45 @@ class __compressed_pair_padding {
8080
template <class _ToPad>
8181
class __compressed_pair_padding<_ToPad, true> {};
8282

83-
# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
84-
_LIBCPP_NO_UNIQUE_ADDRESS __attribute__((__aligned__(::std::__compressed_pair_alignment<T2>))) T1 Initializer1; \
85-
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
86-
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
87-
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _)
88-
89-
# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
90-
_LIBCPP_NO_UNIQUE_ADDRESS \
91-
__attribute__((__aligned__(::std::__compressed_pair_alignment<T2>), \
92-
__aligned__(::std::__compressed_pair_alignment<T3>))) T1 Initializer1; \
93-
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
94-
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
95-
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
96-
_LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
97-
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _)
83+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
84+
# ifdef _LIBCPP_COMPILER_GCC
85+
# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
86+
_LIBCPP_NO_UNIQUE_ADDRESS __attribute__((__aligned__(::std::__compressed_pair_alignment<T2>))) T1 Initializer1; \
87+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
88+
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
89+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _)
90+
91+
# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
92+
_LIBCPP_NO_UNIQUE_ADDRESS \
93+
__attribute__((__aligned__(::std::__compressed_pair_alignment<T2>), \
94+
__aligned__(::std::__compressed_pair_alignment<T3>))) T1 Initializer1; \
95+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
96+
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
97+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
98+
_LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
99+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _)
100+
# else
101+
# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
102+
struct { \
103+
_LIBCPP_NO_UNIQUE_ADDRESS \
104+
__attribute__((__aligned__(::std::__compressed_pair_alignment<T2>))) T1 Initializer1; \
105+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
106+
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
107+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
108+
}
109+
110+
# define _LIBCPP_COMPRESSED_TRIPLE(T1, Initializer1, T2, Initializer2, T3, Initializer3) \
111+
struct { \
112+
_LIBCPP_NO_UNIQUE_ADDRESS \
113+
__attribute__((__aligned__(::std::__compressed_pair_alignment<T2>), \
114+
__aligned__(::std::__compressed_pair_alignment<T3>))) T1 Initializer1; \
115+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding1_, __LINE__, _); \
116+
_LIBCPP_NO_UNIQUE_ADDRESS T2 Initializer2; \
117+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T2> _LIBCPP_CONCAT3(__padding2_, __LINE__, _); \
118+
_LIBCPP_NO_UNIQUE_ADDRESS T3 Initializer3; \
119+
_LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T3> _LIBCPP_CONCAT3(__padding3_, __LINE__, _); \
120+
}
121+
# endif
98122

99123
#else
100124
# define _LIBCPP_COMPRESSED_PAIR(T1, Name1, T2, Name2) \

libcxx/include/string

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,12 @@ public:
974974

975975
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string()
976976
_NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
977-
: __rep_() {
977+
# if _LIBCPP_STD_VER >= 20 // TODO(LLVM 23): Remove this condition; this is a workaround for https://llvm.org/PR154567
978+
: __rep_(__short())
979+
# else
980+
: __rep_()
981+
# endif
982+
{
978983
__annotate_new(0);
979984
}
980985

@@ -984,7 +989,12 @@ public:
984989
# else
985990
_NOEXCEPT
986991
# endif
987-
: __rep_(), __alloc_(__a) {
992+
# if _LIBCPP_STD_VER >= 20 // TODO(LLVM 23): Remove this condition; this is a workaround for https://llvm.org/PR154567
993+
: __rep_(__short()),
994+
# else
995+
: __rep_(),
996+
# endif
997+
__alloc_(__a) {
988998
__annotate_new(0);
989999
}
9901000

libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
1010

11-
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
12-
1311
#include <cstdint>
1412
#include <map>
1513

@@ -90,7 +88,12 @@ struct user_struct {
9088
};
9189

9290
#if __SIZE_WIDTH__ == 64
91+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
92+
# ifdef TEST_COMPILER_GCC
9393
static_assert(sizeof(user_struct) == 32, "");
94+
# else
95+
static_assert(sizeof(user_struct) == 24, "");
96+
# endif
9497
static_assert(TEST_ALIGNOF(user_struct) == 8, "");
9598

9699
static_assert(sizeof(map_alloc<int, std::allocator<std::pair<const int, int> > >) == 24, "");
@@ -119,12 +122,16 @@ static_assert(TEST_ALIGNOF(map_alloc<char, final_small_iter_allocator<std::pair<
119122

120123
struct TEST_ALIGNAS(32) AlignedLess {};
121124

122-
// This part of the ABI has been broken between LLVM 19 and LLVM 20.
123125
static_assert(sizeof(std::map<int, int, AlignedLess>) == 64, "");
124126
static_assert(TEST_ALIGNOF(std::map<int, int, AlignedLess>) == 32, "");
125127

126128
#elif __SIZE_WIDTH__ == 32
129+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
130+
# ifdef TEST_COMPILER_GCC
127131
static_assert(sizeof(user_struct) == 16, "");
132+
# else
133+
static_assert(sizeof(user_struct) == 12, "");
134+
# endif
128135
static_assert(TEST_ALIGNOF(user_struct) == 4, "");
129136

130137
static_assert(sizeof(map_alloc<int, std::allocator<std::pair<const int, int> > >) == 12, "");

libcxx/test/libcxx/containers/associative/set/abi.compile.pass.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
1010

11-
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
12-
1311
#include <cstdint>
1412
#include <set>
1513

@@ -90,7 +88,12 @@ struct user_struct {
9088
};
9189

9290
#if __SIZE_WIDTH__ == 64
91+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
92+
# ifdef TEST_COMPILER_GCC
9393
static_assert(sizeof(user_struct) == 32, "");
94+
# else
95+
static_assert(sizeof(user_struct) == 24, "");
96+
# endif
9497
static_assert(TEST_ALIGNOF(user_struct) == 8, "");
9598

9699
static_assert(sizeof(set_alloc<int, std::allocator<int> >) == 24, "");
@@ -119,12 +122,16 @@ static_assert(TEST_ALIGNOF(set_alloc<char, final_small_iter_allocator<char> >) =
119122

120123
struct TEST_ALIGNAS(32) AlignedLess {};
121124

122-
// This part of the ABI has been broken between LLVM 19 and LLVM 20.
123125
static_assert(sizeof(std::set<int, AlignedLess>) == 64, "");
124126
static_assert(TEST_ALIGNOF(std::set<int, AlignedLess>) == 32, "");
125127

126128
#elif __SIZE_WIDTH__ == 32
129+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
130+
# ifdef TEST_COMPILER_GCC
127131
static_assert(sizeof(user_struct) == 16, "");
132+
# else
133+
static_assert(sizeof(user_struct) == 12, "");
134+
# endif
128135
static_assert(TEST_ALIGNOF(user_struct) == 4, "");
129136

130137
static_assert(sizeof(set_alloc<int, std::allocator<int> >) == 12, "");

libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
// unordered containers changes when bounded unique_ptr is enabled.
1313
// UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr
1414

15-
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
16-
1715
#include <cstdint>
1816
#include <unordered_map>
1917

@@ -94,7 +92,12 @@ struct user_struct {
9492
};
9593

9694
#if __SIZE_WIDTH__ == 64
95+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
96+
# ifdef TEST_COMPILER_GCC
9797
static_assert(sizeof(user_struct) == 48, "");
98+
# else
99+
static_assert(sizeof(user_struct) == 40, "");
100+
# endif
98101
static_assert(TEST_ALIGNOF(user_struct) == 8, "");
99102

100103
static_assert(sizeof(unordered_map_alloc<int, std::allocator<std::pair<const int, int> > >) == 40, "");
@@ -124,13 +127,21 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc<char, final_small_iter_allocator<
124127

125128
struct TEST_ALIGNAS(32) AlignedHash {};
126129
struct UnalignedEqualTo {};
127-
128-
// This part of the ABI has been broken between LLVM 19 and LLVM 20.
130+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
131+
# ifdef TEST_COMPILER_GCC
129132
static_assert(sizeof(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 64, "");
133+
# else
134+
static_assert(sizeof(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 96, "");
135+
# endif
130136
static_assert(TEST_ALIGNOF(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 32, "");
131137

132138
#elif __SIZE_WIDTH__ == 32
139+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
140+
# ifdef TEST_COMPILER_GCC
133141
static_assert(sizeof(user_struct) == 24, "");
142+
# else
143+
static_assert(sizeof(user_struct) == 20, "");
144+
# endif
134145
static_assert(TEST_ALIGNOF(user_struct) == 4, "");
135146

136147
static_assert(sizeof(unordered_map_alloc<int, std::allocator<std::pair<const int, int> > >) == 20, "");
@@ -161,7 +172,12 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc<char, final_small_iter_allocator<
161172
struct TEST_ALIGNAS(32) AlignedHash {};
162173
struct UnalignedEqualTo {};
163174

175+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
176+
# ifdef TEST_COMPILER_GCC
164177
static_assert(sizeof(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 64);
178+
# else
179+
static_assert(sizeof(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 96);
180+
# endif
165181
static_assert(TEST_ALIGNOF(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 32);
166182

167183
#else

libcxx/test/libcxx/containers/associative/unord.set/abi.compile.pass.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
// unordered containers changes when bounded unique_ptr is enabled.
1313
// UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr
1414

15-
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
16-
1715
#include <cstdint>
1816
#include <unordered_set>
1917

@@ -94,7 +92,12 @@ struct user_struct {
9492
};
9593

9694
#if __SIZE_WIDTH__ == 64
95+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
96+
# ifdef TEST_COMPILER_GCC
9797
static_assert(sizeof(user_struct) == 48, "");
98+
# else
99+
static_assert(sizeof(user_struct) == 40, "");
100+
# endif
98101
static_assert(TEST_ALIGNOF(user_struct) == 8, "");
99102

100103
static_assert(sizeof(unordered_set_alloc<int, std::allocator<int> >) == 40, "");
@@ -124,12 +127,21 @@ static_assert(TEST_ALIGNOF(unordered_set_alloc<char, final_small_iter_allocator<
124127
struct TEST_ALIGNAS(32) AlignedHash {};
125128
struct UnalignedEqualTo {};
126129

127-
// This part of the ABI has been broken between LLVM 19 and LLVM 20.
130+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
131+
# ifdef TEST_COMPILER_GCC
128132
static_assert(sizeof(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 64, "");
133+
# else
134+
static_assert(sizeof(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 96, "");
135+
# endif
129136
static_assert(TEST_ALIGNOF(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 32, "");
130137

131138
#elif __SIZE_WIDTH__ == 32
139+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
140+
# ifdef TEST_COMPILER_GCC
132141
static_assert(sizeof(user_struct) == 24, "");
142+
# else
143+
static_assert(sizeof(user_struct) == 20, "");
144+
# endif
133145
static_assert(TEST_ALIGNOF(user_struct) == 4, "");
134146

135147
static_assert(sizeof(unordered_set_alloc<int, std::allocator<int> >) == 20, "");
@@ -159,7 +171,12 @@ static_assert(TEST_ALIGNOF(unordered_set_alloc<char, final_small_iter_allocator<
159171
struct TEST_ALIGNAS(32) AlignedHash {};
160172
struct UnalignedEqualTo {};
161173

174+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
175+
# ifdef TEST_COMPILER_GCC
162176
static_assert(sizeof(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 64);
177+
# else
178+
static_assert(sizeof(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 96);
179+
# endif
163180
static_assert(TEST_ALIGNOF(std::unordered_set<int, AlignedHash, UnalignedEqualTo>) == 32);
164181

165182
#else

libcxx/test/libcxx/containers/sequences/deque/abi.compile.pass.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
1010

11-
// XFAIL: FROZEN-CXX03-HEADERS-FIXME
12-
1311
#include <cstdint>
1412
#include <deque>
1513

@@ -88,14 +86,24 @@ static_assert(sizeof(std::deque<int, min_allocator<int> >) == 48, "");
8886
static_assert(sizeof(std::deque<int, test_allocator<int> >) == 80, "");
8987
static_assert(sizeof(std::deque<int, small_iter_allocator<int> >) == 12, "");
9088
static_assert(sizeof(std::deque<int, final_small_iter_allocator<int> >) == 16, "");
89+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
90+
# ifdef TEST_COMPILER_GCC
9191
static_assert(sizeof(std::deque<int, common_base_allocator<int> >) == 56, "");
92+
# else
93+
static_assert(sizeof(std::deque<int, common_base_allocator<int> >) == 48, "");
94+
# endif
9295

9396
static_assert(sizeof(std::deque<char>) == 48, "");
9497
static_assert(sizeof(std::deque<char, min_allocator<char> >) == 48, "");
9598
static_assert(sizeof(std::deque<char, test_allocator<char> >) == 80, "");
9699
static_assert(sizeof(std::deque<char, small_iter_allocator<char> >) == 12, "");
97100
static_assert(sizeof(std::deque<char, final_small_iter_allocator<char> >) == 16, "");
101+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
102+
# ifdef TEST_COMPILER_GCC
98103
static_assert(sizeof(std::deque<char, common_base_allocator<char> >) == 56, "");
104+
# else
105+
static_assert(sizeof(std::deque<char, common_base_allocator<char> >) == 48, "");
106+
# endif
99107

100108
static_assert(TEST_ALIGNOF(std::deque<int>) == 8, "");
101109
static_assert(TEST_ALIGNOF(std::deque<int, min_allocator<int> >) == 8, "");
@@ -118,14 +126,24 @@ static_assert(sizeof(std::deque<int, min_allocator<int> >) == 24, "");
118126
static_assert(sizeof(std::deque<int, test_allocator<int> >) == 48, "");
119127
static_assert(sizeof(std::deque<int, small_iter_allocator<int> >) == 12, "");
120128
static_assert(sizeof(std::deque<int, final_small_iter_allocator<int> >) == 16, "");
129+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
130+
# ifdef TEST_COMPILER_GCC
121131
static_assert(sizeof(std::deque<int, common_base_allocator<int> >) == 28, "");
132+
# else
133+
static_assert(sizeof(std::deque<int, common_base_allocator<int> >) == 24, "");
134+
# endif
122135

123136
static_assert(sizeof(std::deque<char>) == 24, "");
124137
static_assert(sizeof(std::deque<char, min_allocator<char> >) == 24, "");
125138
static_assert(sizeof(std::deque<char, test_allocator<char> >) == 48, "");
126139
static_assert(sizeof(std::deque<char, small_iter_allocator<char> >) == 12, "");
127140
static_assert(sizeof(std::deque<char, final_small_iter_allocator<char> >) == 16, "");
141+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
142+
# ifdef TEST_COMPILER_GCC
128143
static_assert(sizeof(std::deque<char, common_base_allocator<char> >) == 28, "");
144+
# else
145+
static_assert(sizeof(std::deque<char, common_base_allocator<char> >) == 24, "");
146+
# endif
129147

130148
static_assert(TEST_ALIGNOF(std::deque<int>) == 4, "");
131149
static_assert(TEST_ALIGNOF(std::deque<int, min_allocator<int> >) == 4, "");

0 commit comments

Comments
 (0)