@@ -638,6 +638,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
638
638
#include < __utility/forward.h>
639
639
#include < __utility/is_pointer_in_range.h>
640
640
#include < __utility/move.h>
641
+ #include < __utility/scope_guard.h>
641
642
#include < __utility/swap.h>
642
643
#include < __utility/unreachable.h>
643
644
#include < climits>
@@ -929,6 +930,13 @@ private:
929
930
930
931
_LIBCPP_COMPRESSED_PAIR (__rep, __rep_, allocator_type, __alloc_);
931
932
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
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void operator ()() { __str_.__annotate_new (__str_.size ()); }
938
+ };
939
+
932
940
// Construct a string with the given allocator and enough storage to hold `__size` characters, but
933
941
// don't initialize the characters. The contents of the string, including the null terminator, must be
934
942
// initialized separately.
@@ -2171,6 +2179,7 @@ private:
2171
2179
__alloc_ = __str.__alloc_ ;
2172
2180
} else {
2173
2181
__annotate_delete ();
2182
+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
2174
2183
allocator_type __a = __str.__alloc_ ;
2175
2184
auto __allocation = std::__allocate_at_least (__a, __str.__get_long_cap ());
2176
2185
__begin_lifetime (__allocation.ptr , __allocation.count );
@@ -2180,7 +2189,6 @@ private:
2180
2189
__set_long_pointer (__allocation.ptr );
2181
2190
__set_long_cap (__allocation.count );
2182
2191
__set_long_size (__str.size ());
2183
- __annotate_new (__get_long_size ());
2184
2192
}
2185
2193
}
2186
2194
}
@@ -2508,6 +2516,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
2508
2516
size_type __cap =
2509
2517
__old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1 ;
2510
2518
__annotate_delete ();
2519
+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
2511
2520
auto __allocation = std::__allocate_at_least (__alloc_, __cap + 1 );
2512
2521
pointer __p = __allocation.ptr ;
2513
2522
__begin_lifetime (__p, __allocation.count );
@@ -2526,7 +2535,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
2526
2535
__old_sz = __n_copy + __n_add + __sec_cp_sz;
2527
2536
__set_long_size (__old_sz);
2528
2537
traits_type::assign (__p[__old_sz], value_type ());
2529
- __annotate_new (__old_sz);
2530
2538
}
2531
2539
2532
2540
// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
@@ -2550,7 +2558,6 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
2550
2558
pointer __old_p = __get_pointer ();
2551
2559
size_type __cap =
2552
2560
__old_cap < __ms / 2 - __alignment ? __recommend (std::max (__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1 ;
2553
- __annotate_delete ();
2554
2561
auto __allocation = std::__allocate_at_least (__alloc_, __cap + 1 );
2555
2562
pointer __p = __allocation.ptr ;
2556
2563
__begin_lifetime (__p, __allocation.count );
@@ -2575,11 +2582,12 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
2575
2582
size_type __n_copy,
2576
2583
size_type __n_del,
2577
2584
size_type __n_add) {
2585
+ __annotate_delete ();
2586
+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
2578
2587
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
2579
2588
__grow_by (__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
2580
2589
_LIBCPP_SUPPRESS_DEPRECATED_POP
2581
2590
__set_long_size (__old_sz - __n_del + __n_add);
2582
- __annotate_new (__old_sz - __n_del + __n_add);
2583
2591
}
2584
2592
2585
2593
// assign
@@ -3364,6 +3372,7 @@ template <class _CharT, class _Traits, class _Allocator>
3364
3372
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
3365
3373
basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend (size_type __target_capacity) {
3366
3374
__annotate_delete ();
3375
+ auto __guard = std::__make_scope_guard (__annotate_new_size (*this ));
3367
3376
size_type __cap = capacity ();
3368
3377
size_type __sz = size ();
3369
3378
@@ -3395,7 +3404,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
3395
3404
// due to swapping the elements.
3396
3405
if (__allocation.count - 1 > __target_capacity) {
3397
3406
__alloc_traits::deallocate (__alloc_, __allocation.ptr , __allocation.count );
3398
- __annotate_new (__sz); // Undoes the __annotate_delete()
3399
3407
return ;
3400
3408
}
3401
3409
__new_data = __allocation.ptr ;
@@ -3420,7 +3428,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
3420
3428
__set_long_pointer (__new_data);
3421
3429
} else
3422
3430
__set_short_size (__sz);
3423
- __annotate_new (__sz);
3424
3431
}
3425
3432
3426
3433
template <class _CharT , class _Traits , class _Allocator >
0 commit comments