[libcxx-commits] [libcxx] [libc++][test] Drop _BitInt(96) byteswap padding check on 32-bit x86 (PR #205295)
Xavier Roche via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Jun 27 04:00:53 PDT 2026
https://github.com/xroche updated https://github.com/llvm/llvm-project/pull/205295
>From 4ae67649d4e8107f68f160a085028d714f814eb7 Mon Sep 17 00:00:00 2001
From: Xavier Roche <xavier.roche at algolia.com>
Date: Tue, 23 Jun 2026 10:39:19 +0200
Subject: [PATCH 1/2] [libc++][test] Drop _BitInt(96) byteswap padding check on
32-bit x86
byteswap.verify.cpp expected std::byteswap(unsigned _BitInt(96)) to be
rejected for having padding bits. That holds on x86_64, where the type
is 16 bytes (32 padding bits), but not on 32-bit x86: there _BitInt(96)
is 12 bytes with no padding, so byteswap is well-formed and the expected
diagnostic never fires. The Android i386 builder caught this.
Remove the width-96 case. Widths 80 and 112 still cover byte-aligned
padded types above 64 bits, and pad on both 32- and 64-bit targets.
Assisted-by: Claude (Anthropic)
Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>
---
.../test/std/numerics/bit/byteswap.verify.cpp | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
diff --git a/libcxx/test/std/numerics/bit/byteswap.verify.cpp b/libcxx/test/std/numerics/bit/byteswap.verify.cpp
index 5a205d9ec5051..f1614d11c9e0d 100644
--- a/libcxx/test/std/numerics/bit/byteswap.verify.cpp
+++ b/libcxx/test/std/numerics/bit/byteswap.verify.cpp
@@ -68,10 +68,10 @@ void test_unsigned_65() {
}
# endif
-// Byte-aligned widths whose value bits don't fill the object representation.
-// On platforms where sizeof(_BitInt(N)) rounds up to a power of two, these
-// types have padding bits in the high-order storage positions even though
-// their value width is a multiple of CHAR_BIT.
+// Byte-aligned widths whose value bits don't fill the object representation,
+// so the high-order storage holds padding bits. Only widths that pad on every
+// target are listed; 96 is omitted because _BitInt(96) is 12 bytes with no
+// padding on 32-bit x86.
void test_unsigned_24() {
// sizeof(_BitInt(24)) == 4 on x86_64; 8 padding bits.
unsigned _BitInt(24) v = 0;
@@ -114,15 +114,6 @@ void test_unsigned_80() {
}
# endif
-# if __BITINT_MAXWIDTH__ >= 96
-void test_unsigned_96() {
- // sizeof(_BitInt(96)) == 16 on x86_64; 32 padding bits.
- unsigned _BitInt(96) v = 0;
- // expected-error-re@*:* {{{{(std::byteswap requires T to have no padding bits|byteswap is unimplemented for integral types of this size)}}}}
- (void)std::byteswap(v);
-}
-# endif
-
# if __BITINT_MAXWIDTH__ >= 112
void test_unsigned_112() {
// sizeof(_BitInt(112)) == 16 on x86_64; 16 padding bits.
>From f08a2a8d77c01e2a58ae7ce28a65e50e7e81a1a5 Mon Sep 17 00:00:00 2001
From: Xavier Roche <xavier.roche at algolia.com>
Date: Tue, 23 Jun 2026 11:07:34 +0200
Subject: [PATCH 2/2] [libc++][test] Gate _BitInt(96) byteswap case on
!__i386__ instead of removing
Restore test_unsigned_96, dropped in the previous commit, behind
!defined(__i386__). The zero-padding behavior is specific to the i386
psABI, which aligns _BitInt to 4 bytes and packs _BitInt(96) into 12
bytes. Every other target, including 32-bit arm, riscv32, ppc32, mips32
and sparc32, gives it 16 bytes with 32 padding bits, so the case still
exercises the padding-bit Mandate everywhere except 32-bit x86.
sizeof is not available to the preprocessor, so the guard is a target
check rather than a direct has-padding predicate. Addresses review
feedback to gate the case rather than delete it.
Assisted-by: Claude (Anthropic)
Co-Authored-By: Claude Opus 4.6 <noreply at anthropic.com>
---
.../test/std/numerics/bit/byteswap.verify.cpp | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/std/numerics/bit/byteswap.verify.cpp b/libcxx/test/std/numerics/bit/byteswap.verify.cpp
index f1614d11c9e0d..f9b6954f525da 100644
--- a/libcxx/test/std/numerics/bit/byteswap.verify.cpp
+++ b/libcxx/test/std/numerics/bit/byteswap.verify.cpp
@@ -69,9 +69,8 @@ void test_unsigned_65() {
# endif
// Byte-aligned widths whose value bits don't fill the object representation,
-// so the high-order storage holds padding bits. Only widths that pad on every
-// target are listed; 96 is omitted because _BitInt(96) is 12 bytes with no
-// padding on 32-bit x86.
+// so the high-order storage holds padding bits even though the value width is
+// a multiple of CHAR_BIT.
void test_unsigned_24() {
// sizeof(_BitInt(24)) == 4 on x86_64; 8 padding bits.
unsigned _BitInt(24) v = 0;
@@ -114,6 +113,18 @@ void test_unsigned_80() {
}
# endif
+// 32-bit x86 packs _BitInt(96) into 12 bytes (no padding), so std::byteswap
+// accepts it there; gate the case out. sizeof isn't available to the
+// preprocessor, so this is a target check rather than a has-padding predicate.
+# if __BITINT_MAXWIDTH__ >= 96 && !defined(__i386__)
+void test_unsigned_96() {
+ // sizeof(_BitInt(96)) == 16 here; 32 padding bits.
+ unsigned _BitInt(96) v = 0;
+ // expected-error-re@*:* {{{{(std::byteswap requires T to have no padding bits|byteswap is unimplemented for integral types of this size)}}}}
+ (void)std::byteswap(v);
+}
+# endif
+
# if __BITINT_MAXWIDTH__ >= 112
void test_unsigned_112() {
// sizeof(_BitInt(112)) == 16 on x86_64; 16 padding bits.
More information about the libcxx-commits
mailing list