@@ -638,6 +638,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
638638#include < __utility/forward.h>
639639#include < __utility/is_pointer_in_range.h>
640640#include < __utility/move.h>
641+ #include < __utility/scope_guard.h>
641642#include < __utility/swap.h>
642643#include < __utility/unreachable.h>
643644#include < climits>
@@ -929,6 +930,13 @@ private:
929930
930931 _LIBCPP_COMPRESSED_PAIR (__rep, __rep_, allocator_type, __alloc_);
931932
933+ // annotate the string with its size() at scope exit. The string has to be in a valid state at that point.
934+ struct __annotate_new_size {
935+ basic_string& __str_;
936+
937+ void operator ()() { __str_.__annotate_new (__str_.size ()); }
938+ };
939+
932940 // Construct a string with the given allocator and enough storage to hold `__size` characters, but
933941 // don't initialize the characters. The contents of the string, including the null terminator, must be
934942 // initialized separately.
@@ -2169,6 +2177,7 @@ private:
21692177 __alloc_ = __str.__alloc_ ;
21702178 } else {
21712179 __annotate_delete ();
2180+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
21722181 allocator_type __a = __str.__alloc_ ;
21732182 auto __allocation = std::__allocate_at_least (__a, __str.__get_long_cap ());
21742183 __begin_lifetime (__allocation.ptr , __allocation.count );
@@ -2178,7 +2187,6 @@ private:
21782187 __set_long_pointer (__allocation.ptr );
21792188 __set_long_cap (__allocation.count );
21802189 __set_long_size (__str.size ());
2181- __annotate_new (__get_long_size ());
21822190 }
21832191 }
21842192 }
@@ -2506,6 +2514,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
25062514 size_type __cap =
25072515 __old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1 ;
25082516 __annotate_delete ();
2517+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
25092518 auto __allocation = std::__allocate_at_least (__alloc_, __cap + 1 );
25102519 pointer __p = __allocation.ptr ;
25112520 __begin_lifetime (__p, __allocation.count );
@@ -2524,7 +2533,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
25242533 __old_sz = __n_copy + __n_add + __sec_cp_sz;
25252534 __set_long_size (__old_sz);
25262535 traits_type::assign (__p[__old_sz], value_type ());
2527- __annotate_new (__old_sz);
25282536}
25292537
25302538// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
@@ -2548,7 +2556,6 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
25482556 pointer __old_p = __get_pointer ();
25492557 size_type __cap =
25502558 __old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1 ;
2551- __annotate_delete ();
25522559 auto __allocation = std::__allocate_at_least (__alloc_, __cap + 1 );
25532560 pointer __p = __allocation.ptr ;
25542561 __begin_lifetime (__p, __allocation.count );
@@ -2573,11 +2580,12 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
25732580 size_type __n_copy,
25742581 size_type __n_del,
25752582 size_type __n_add) {
2583+ __annotate_delete ();
2584+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
25762585 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
25772586 __grow_by (__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
25782587 _LIBCPP_SUPPRESS_DEPRECATED_POP
25792588 __set_long_size (__old_sz - __n_del + __n_add);
2580- __annotate_new (__old_sz - __n_del + __n_add);
25812589}
25822590
25832591// assign
@@ -3367,6 +3375,7 @@ template <class _CharT, class _Traits, class _Allocator>
33673375inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
33683376basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend (size_type __target_capacity) {
33693377 __annotate_delete ();
3378+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
33703379 size_type __cap = capacity ();
33713380 size_type __sz = size ();
33723381
@@ -3398,7 +3407,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
33983407 // due to swapping the elements.
33993408 if (__allocation.count - 1 > __target_capacity) {
34003409 __alloc_traits::deallocate (__alloc_, __allocation.ptr , __allocation.count );
3401- __annotate_new (__sz); // Undoes the __annotate_delete()
34023410 return ;
34033411 }
34043412 __new_data = __allocation.ptr ;
@@ -3423,7 +3431,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
34233431 __set_long_pointer (__new_data);
34243432 } else
34253433 __set_short_size (__sz);
3426- __annotate_new (__sz);
34273434}
34283435
34293436template <class _CharT , class _Traits , class _Allocator >
0 commit comments