[libcxx-commits] [libcxx] [libc++] Fix basic_string not allowing max_size() elements to be stored (PR #125423)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Feb 20 07:20:05 PST 2025
================
@@ -1302,10 +1302,10 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type max_size() const _NOEXCEPT {
size_type __m = __alloc_traits::max_size(__alloc_);
if (__m <= std::numeric_limits<size_type>::max() / 2) {
- return __m - __alignment;
+ return ((__m - __alignment) & ~size_type(__endian_factor - 1)) - 1;
----------------
ldionne wrote:
Here's the little table I did for my understanding:
```
endian factor = 1
-----------------
factor-1 = 0000000000000000000000
~ = 1111111111111111111111
m-align = xxxxxxxxxxxxxxxxxxxxxx
& = xxxxxxxxxxxxxxxxxxxxxx
So the result is unchanged
endian factor = 2
-----------------
factor-1 = 0000000000000000000001
~ = 1111111111111111111110
m-align = xxxxxxxxxxxxxxxxxxxxxx
& = xxxxxxxxxxxxxxxxxxxxx0
So the bitand is always even, and the end result is always odd because we subtract 1
```
Since `__endian_factor` is a compile-time constant we should be able to rewrite like this without impacting codegen (IMO this is easier to follow):
```c++
if (__m <= std::numeric_limits<size_type>::max() / 2) {
size_type __res = __m - __alignment;
if (__endian_factor == 2)
__res &= ~size_type(1); // make even, explain why in a short comment
__res -= 1; // max_size() doesn't include the null terminator
}
```
WDYT?
https://github.com/llvm/llvm-project/pull/125423
More information about the libcxx-commits
mailing list