[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
Fri Oct 30 20:41:34 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Himadhith
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/236867.diff
1 Files Affected:
- (modified) libcxx/include/string (+9-1)
``````````diff
diff --git a/libcxx/include/string b/libcxx/include/string
index 33175c115fd10c..25bf9e158f5d6b 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -797,12 +797,20 @@ 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) + _LIBCPP_ALIGNOF(pointer) - 1) & ~(_LIBCPP_ALIGNOF(pointer) - 1)) -
+ 2 * sizeof(size_type)>
+ __padding_;
size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1;
size_type __is_long_ : 1;
};
``````````
</details>
https://github.com/llvm/llvm-project/pull/236867
More information about the libcxx-commits
mailing list