@@ -825,31 +825,44 @@ public:
825825private:
826826 static_assert (CHAR_BIT == 8 , " This implementation assumes that one byte contains 8 bits" );
827827
828- # ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
829-
828+ // Attribute 'packed' is used to keep the layout compatible with the
829+ // previous definition that did not use bit fields. This is because on
830+ // some platforms bit fields have a default size rather than the actual
831+ // size used, e.g., it is 4 bytes on AIX. See D128285 for details.
830832 struct __long {
831833 __long () = default ;
832834
833- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long (__alloc_result __alloc, size_type __size)
834- : __data_(__alloc.ptr), __size_(__size), __cap_(__alloc.count / __endian_factor), __is_long_(true ) {
835- _LIBCPP_ASSERT_INTERNAL (!__fits_in_sso (__alloc.count ), " Long capacity should always be larger than the SSO" );
835+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long (_Allocator& __alloc, size_type __size)
836+ : __is_long_(true ), __size_(__size) {
837+ _LIBCPP_ASSERT_INTERNAL (!__fits_in_sso (__size), " Long capacity should always be larger than the SSO" );
838+ auto __allocation = std::__allocate_at_least (__alloc, __recommend (__size) + 1 );
839+
840+ __cap_ = __allocation.count / __endian_factor;
841+ __data_ = __allocation.ptr ;
842+
843+ if (__libcpp_is_constant_evaluated ()) {
844+ for (size_type __i = 0 ; __i != __allocation.count ; ++__i)
845+ std::__construct_at (std::addressof (__allocation.ptr [__i]));
846+ }
836847 }
837848
849+ # ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
838850 pointer __data_;
839851 size_type __size_;
840- size_type __cap_ : sizeof (size_type) * CHAR_BIT - 1 ;
852+ size_type __cap_ : sizeof (size_type) * CHAR_BIT - 1 ;
841853 size_type __is_long_ : 1 ;
854+ # else
855+ struct _LIBCPP_PACKED {
856+ size_type __is_long_ : 1 ;
857+ size_type __cap_ : sizeof (size_type) * CHAR_BIT - 1 ;
858+ };
859+ size_type __size_;
860+ pointer __data_;
861+ # endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
842862 };
843863
844864 enum { __min_cap = (sizeof (__long) - 1 ) / sizeof (value_type) > 2 ? (sizeof (__long) - 1 ) / sizeof (value_type) : 2 };
845865
846- struct __short {
847- value_type __data_[__min_cap];
848- _LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof (value_type) - 1 > __padding_;
849- unsigned char __size_ : 7 ;
850- unsigned char __is_long_ : 1 ;
851- };
852-
853866 // The __endian_factor is required because the field we use to store the size
854867 // has one fewer bit than it would if it were not a bitfield.
855868 //
@@ -862,42 +875,22 @@ private:
862875 // If the MSB is used for the short-flag, the max_size() is numeric_limits<size_type>::max() / 2.
863876 // This does not impact the short string representation, since we never need the MSB
864877 // for representing the size of a short string anyway.
865-
866- # ifdef _LIBCPP_BIG_ENDIAN
878+ #if defined(_LIBCPP_BIG_ENDIAN) == defined(_LIBCPP_ABI_ALTERNATE_STRING_LAYOUT)
867879 static const size_type __endian_factor = 2 ;
868- # else
869- static const size_type __endian_factor = 1 ;
870- # endif
871-
872- # else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
873-
874- # ifdef _LIBCPP_BIG_ENDIAN
880+ #else
875881 static const size_type __endian_factor = 1 ;
876- # else
877- static const size_type __endian_factor = 2 ;
878- # endif
879-
880- // Attribute 'packed' is used to keep the layout compatible with the
881- // previous definition that did not use bit fields. This is because on
882- // some platforms bit fields have a default size rather than the actual
883- // size used, e.g., it is 4 bytes on AIX. See D128285 for details.
884- struct __long {
885- __long () = default ;
882+ #endif
886883
887- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __long (__alloc_result __alloc, size_type __size)
888- : __is_long_(true ), __cap_(__alloc.count / __endian_factor), __size_(__size), __data_(__alloc.ptr) {
889- _LIBCPP_ASSERT_INTERNAL (!__fits_in_sso (__alloc.count ), " Long capacity should always be larger than the SSO" );
890- }
884+ # ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
891885
892- struct _LIBCPP_PACKED {
893- size_type __is_long_ : 1 ;
894- size_type __cap_ : sizeof (size_type) * CHAR_BIT - 1 ;
895- };
896- size_type __size_;
897- pointer __data_;
886+ struct __short {
887+ value_type __data_[__min_cap];
888+ _LIBCPP_NO_UNIQUE_ADDRESS __padding<sizeof (value_type) - 1 > __padding_;
889+ unsigned char __size_ : 7 ;
890+ unsigned char __is_long_ : 1 ;
898891 };
899892
900- enum { __min_cap = ( sizeof (__long) - 1 ) / sizeof (value_type) > 2 ? ( sizeof (__long) - 1 ) / sizeof (value_type) : 2 };
893+ # else // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
901894
902895 struct __short {
903896 struct _LIBCPP_PACKED {
@@ -2255,19 +2248,6 @@ private:
22552248 // These functions are only responsible for managing the buffer itself, not the value inside the buffer. As such,
22562249 // none of these facilities ensure that there is a null terminator at `data()[size()]`.
22572250
2258- // Allocate a buffer of __capacity size with __alloc and return it
2259- _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX20 __long
2260- __allocate_long_buffer (_Allocator& __alloc, size_type __capacity) {
2261- auto __buffer = std::__allocate_at_least (__alloc, __recommend (__capacity) + 1 );
2262-
2263- if (__libcpp_is_constant_evaluated ()) {
2264- for (size_type __i = 0 ; __i != __buffer.count ; ++__i)
2265- std::__construct_at (std::addressof (__buffer.ptr [__i]));
2266- }
2267-
2268- return __long (__buffer, __capacity);
2269- }
2270-
22712251 // Replace the current buffer with __new_rep. Deallocate the old long buffer if it exists.
22722252 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __reset_internal_buffer (__rep __new_rep = __short()) {
22732253 __annotate_delete ();
@@ -2290,7 +2270,7 @@ private:
22902270 __annotate_new (__size);
22912271 return __get_short_pointer ();
22922272 } else {
2293- __rep_. __l = __allocate_long_buffer (__alloc_, __size);
2273+ __rep_ = __long (__alloc_, __size);
22942274 __annotate_new (__size);
22952275 return __get_long_pointer ();
22962276 }
@@ -2447,7 +2427,7 @@ private:
24472427 __annotate_delete ();
24482428 auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
24492429 auto __alloc = __str.__alloc_ ;
2450- __reset_internal_buffer (__allocate_long_buffer (__alloc, __str.size ()));
2430+ __reset_internal_buffer (__long (__alloc, __str.size ()));
24512431 __alloc_ = std::move (__alloc);
24522432 }
24532433 }
@@ -2700,8 +2680,8 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
27002680 size_type __cap =
27012681 __old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
27022682 __annotate_delete ();
2703- auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
2704- __long __buffer = __allocate_long_buffer (__alloc_, __cap);
2683+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
2684+ __long __buffer (__alloc_, __cap);
27052685 if (__n_copy != 0 )
27062686 traits_type::copy (std::__to_address (__buffer.__data_ ), std::__to_address (__old_p), __n_copy);
27072687 if (__n_add != 0 )
@@ -2737,7 +2717,7 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
27372717 pointer __old_p = __get_pointer ();
27382718 size_type __cap =
27392719 __old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms;
2740- __long __buffer = __allocate_long_buffer (__alloc_, __cap);
2720+ __long __buffer (__alloc_, __cap);
27412721 if (__n_copy != 0 )
27422722 traits_type::copy (std::__to_address (__buffer.__data_ ), std::__to_address (__old_p), __n_copy);
27432723 size_type __sec_cp_sz = __old_sz - __n_del - __n_copy;
@@ -3394,7 +3374,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
33943374 return ;
33953375
33963376 __annotation_guard __g (*this );
3397- __long __buffer = __allocate_long_buffer (__alloc_, __requested_capacity);
3377+ __long __buffer (__alloc_, __requested_capacity);
33983378 __buffer.__size_ = size ();
33993379 traits_type::copy (std::__to_address (__buffer.__data_ ), data (), __buffer.__size_ + 1 );
34003380 __reset_internal_buffer (__buffer);
@@ -3425,7 +3405,7 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat
34253405 try {
34263406# endif // _LIBCPP_HAS_EXCEPTIONS
34273407 __annotation_guard __g (*this );
3428- __long __buffer = __allocate_long_buffer (__alloc_, __size);
3408+ __long __buffer (__alloc_, __size);
34293409
34303410 // The Standard mandates shrink_to_fit() does not increase the capacity.
34313411 // With equal capacity keep the existing buffer. This avoids extra work
0 commit comments