[libcxx-commits] [libcxx] [libc++] Fix the long/short flag position of basic_string for a narrow size_type (PR #236867)
via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Oct 29 10:51:52 PDT 2026
https://github.com/Himadhith created https://github.com/llvm/llvm-project/pull/236867
This patch fixes `basic_string` for allocators with a `size_type` narrower than 4 bytes under `_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT`.
In that layout `__is_long()` reads the flag from the last byte of the object through `__short`. `__long` stores its flag in the last bitfield after `__size_`.
On a 64-bit:
For a `uint8_t` `size_type` that is byte 9 while `alignof(pointer)` pads the struct to 16 bytes. The flag is written at byte 9 and read at byte 15, which is never written, so every long string looks short.
This change inserts a `__padding` member between `__size_` and `__cap_` in `__long`. Its size is the gap between `2 * sizeof(size_type)` and the next multiple of `alignof(pointer)`, which pushes `__cap_` and `__is_long_` to the last bytes of the object so the `__long` flag aliases the `__short` flag again.
The member is `_LIBCPP_NO_UNIQUE_ADDRESS`, so when the gap is 0 it occupies no space.
>From d7d0601a73090af0b7a6f358819a19b553abf08e Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Thu, 29 Oct 2026 23:08:24 +0530
Subject: [PATCH] [libc++] Fix the long/short flag position of basic_string for
a narrow size_type
---
libcxx/include/string | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 33175c115fd10c..b03fc1f83edf55 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -797,12 +797,14 @@ private:
__long() = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long(__alloc_result __alloc, size_type __size)
- : __data_(__alloc.ptr), __size_(__size), __cap_(__alloc.count / __endian_factor), __is_long_(true) {
+ : __data_(__alloc.ptr), __size_(__size), __padding_(), __cap_(__alloc.count / __endian_factor), __is_long_(true) {
_LIBCPP_ASSERT_INTERNAL(!__fits_in_sso(__alloc.count), "Long capacity should always be larger than the SSO");
}
pointer __data_;
size_type __size_;
+ _LIBCPP_NO_UNIQUE_ADDRESS __padding<((2 * sizeof(size_type) + alignof(pointer) - 1) & ~(alignof(pointer) - 1)) -
+ 2 * sizeof(size_type)> __padding_;
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
size_type __is_long_ : 1;
};
More information about the libcxx-commits
mailing list