1212
1313// void shrink_to_fit(); // constexpr since C++20
1414
15- // Make sure we use an allocation returned by allocate_at_least if it is smaller than the current allocation
16- // even if it contains more bytes than we requested
17-
1815#include < cassert>
1916#include < string>
2017
18+ #include " asan_testing.h"
19+ #include " increasing_allocator.h"
20+
2121template <typename T>
2222struct oversizing_allocator {
2323 using value_type = T;
@@ -37,6 +37,9 @@ bool operator==(oversizing_allocator<T>, oversizing_allocator<U>) {
3737 return true ;
3838}
3939
40+ // Make sure we use an allocation returned by allocate_at_least if it is smaller than the current allocation
41+ // even if it contains more bytes than we requested.
42+ // Fix issue: https://github.com/llvm/llvm-project/pull/115659
4043void test_oversizing_allocator () {
4144 std::basic_string<char , std::char_traits<char >, oversizing_allocator<char >> s{
4245 " String does not fit in the internal buffer and is a bit longer" };
@@ -48,8 +51,37 @@ void test_oversizing_allocator() {
4851 assert (s.size () == size);
4952}
5053
54+ // Ensure that the libc++ implementation of shrink_to_fit does NOT swap buffer with equal allocation sizes
55+ void test_no_swap_with_equal_allocation_size () {
56+ { // Test with custom allocator with a minimum allocation size
57+ std::basic_string<char , std::char_traits<char >, min_size_allocator<128 , char > > s (
58+ " A long string exceeding SSO limit but within min alloc size" );
59+ std::size_t capacity = s.capacity ();
60+ std::size_t size = s.size ();
61+ auto data = s.data ();
62+ s.shrink_to_fit ();
63+ assert (s.capacity () <= capacity);
64+ assert (s.size () == size);
65+ assert (is_string_asan_correct (s));
66+ assert (s.capacity () == capacity && s.data () == data);
67+ }
68+ { // Test with custom allocator with a minimum power of two allocation size
69+ std::basic_string<char , std::char_traits<char >, pow2_allocator<char > > s (
70+ " This is a long string that exceeds the SSO limit" );
71+ std::size_t capacity = s.capacity ();
72+ std::size_t size = s.size ();
73+ auto data = s.data ();
74+ s.shrink_to_fit ();
75+ assert (s.capacity () <= capacity);
76+ assert (s.size () == size);
77+ assert (is_string_asan_correct (s));
78+ assert (s.capacity () == capacity && s.data () == data);
79+ }
80+ }
81+
5182int main (int , char **) {
5283 test_oversizing_allocator ();
84+ test_no_swap_with_equal_allocation_size ();
5385
5486 return 0 ;
5587}
0 commit comments