xref: /llvm-project/libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp (revision 3497500946c9b6a1b2e1452312a24c41ee412b34)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <string>
10 
11 // void reserve(); // Deprecated in C++20.
12 // void reserve(size_type);
13 
14 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -D_LIBCPP_ENABLE_CXX26_REMOVED_STRING_RESERVE
15 
16 // This test ensures that libc++ implements https://wg21.link/P0966R1 (reserve never shrinks)
17 // even before C++20. This is required in order to avoid ODR violations because basic_string::reserve(size)
18 // is compiled into the shared library. Hence, it needs to have the same definition in all Standard modes.
19 //
20 // However, note that reserve() does shrink, and it does so in all Standard modes.
21 //
22 // Reported as https://llvm.org/PR53170.
23 
24 // reserve(n) used to shrink the string until https://llvm.org/D117332 was shipped in LLVM 14.
25 // XFAIL: using-built-library-before-llvm-14
26 
27 #include <string>
28 #include <stdexcept>
29 #include <cassert>
30 
31 #include "test_macros.h"
32 #include "min_allocator.h"
33 
34 template <class S>
test()35 TEST_CONSTEXPR_CXX20 bool test() {
36   // Test that a call to reserve() does shrink the string.
37   if (!TEST_IS_CONSTANT_EVALUATED) {
38     S s(1000, 'a');
39     typename S::size_type old_cap = s.capacity();
40     s.resize(20);
41     assert(s.capacity() == old_cap);
42 
43     s.reserve();
44     assert(s.capacity() < old_cap);
45   }
46 
47   // Test that a call to reserve(smaller-than-capacity) never shrinks the string.
48   {
49     S s(1000, 'a');
50     typename S::size_type old_cap = s.capacity();
51     s.resize(20);
52     assert(s.capacity() == old_cap);
53 
54     s.reserve(10);
55     assert(s.capacity() == old_cap);
56   }
57 
58   // In particular, test that reserve(0) does NOT shrink the string.
59   {
60     S s(1000, 'a');
61     typename S::size_type old_cap = s.capacity();
62     s.resize(20);
63     assert(s.capacity() == old_cap);
64 
65     s.reserve(0);
66     assert(s.capacity() == old_cap);
67   }
68 
69   return true;
70 }
71 
main(int,char **)72 int main(int, char**) {
73   test<std::string>();
74 
75 #if TEST_STD_VER >= 11
76   test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >();
77 #endif
78 
79 #if TEST_STD_VER > 17
80   static_assert(test<std::string>());
81 #endif
82 
83   return 0;
84 }
85