[mlir][Vector] Fix `vector.shuffle` folder for poison indices (#124863)
[llvm-project.git] / libcxx / test / std / containers / sequences / vector / vector.capacity / reserve_exceptions.pass.cpp
blobc381e23a04d02da77891801086f734b4a5c2085d
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: no-exceptions
11 // This test file validates that std::vector<T>::reserve provides the strong exception guarantee if T is
12 // Cpp17MoveInsertable and no exception is thrown by the move constructor of T during the reserve call.
13 // It also checks that if T's move constructor is not noexcept, reserve provides only the basic exception
14 // guarantee.
16 #include <cstddef>
17 #include <memory>
18 #include <type_traits>
19 #include <vector>
21 #include "../common.h"
22 #include "MoveOnly.h"
23 #include "count_new.h"
24 #include "increasing_allocator.h"
25 #include "min_allocator.h"
26 #include "test_allocator.h"
27 #include "test_iterators.h"
28 #include "test_macros.h"
30 template <typename T, typename Alloc>
31 void test_allocation_exception_for_strong_guarantee(
32 std::vector<T, Alloc>& v, const std::vector<T>& values, std::size_t new_cap) {
33 assert(v.size() == values.size());
34 T* old_data = v.data();
35 std::size_t old_size = v.size();
36 std::size_t old_cap = v.capacity();
38 try {
39 v.reserve(new_cap);
40 } catch (...) { // std::length_error, std::bad_alloc
41 assert(v.data() == old_data);
42 assert(v.size() == old_size);
43 assert(v.capacity() == old_cap);
44 for (std::size_t i = 0; i < v.size(); ++i)
45 assert(v[i] == values[i]);
49 template <typename T, typename Alloc>
50 void test_copy_ctor_exception_for_strong_guarantee(std::vector<throwing_data<T>, Alloc>& v,
51 const std::vector<T>& values) {
52 assert(v.empty() && !values.empty());
53 int throw_after = values.size() + values.size() / 2; // Trigger an exception halfway through reallocation
54 v.reserve(values.size());
55 for (std::size_t i = 0; i < values.size(); ++i)
56 v.emplace_back(values[i], throw_after);
58 throwing_data<T>* old_data = v.data();
59 std::size_t old_size = v.size();
60 std::size_t old_cap = v.capacity();
61 std::size_t new_cap = 2 * old_cap;
63 try {
64 v.reserve(new_cap);
65 } catch (...) {
66 assert(v.data() == old_data);
67 assert(v.size() == old_size);
68 assert(v.capacity() == old_cap);
69 for (std::size_t i = 0; i < v.size(); ++i)
70 assert(v[i].data_ == values[i]);
74 #if TEST_STD_VER >= 11
76 template <typename T, typename Alloc>
77 void test_move_ctor_exception_for_basic_guarantee(std::vector<move_only_throwing_t<T>, Alloc>& v,
78 const std::vector<T>& values) {
79 assert(v.empty() && !values.empty());
80 int throw_after = values.size() + values.size() / 2; // Trigger an exception halfway through reallocation
81 v.reserve(values.size());
82 for (std::size_t i = 0; i < values.size(); ++i)
83 v.emplace_back(values[i], throw_after);
85 try {
86 v.reserve(2 * v.capacity());
87 } catch (...) {
88 use_unspecified_but_valid_state_vector(v);
92 #endif
94 // Check the strong exception guarantee during reallocation failures
95 void test_allocation_exceptions() {
97 // Tests for std::length_error during reallocation failures
100 std::vector<int> v;
101 test_allocation_exception_for_strong_guarantee(v, std::vector<int>(), v.max_size() + 1);
103 check_new_delete_called();
106 int a[] = {1, 2, 3, 4, 5};
107 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
108 std::vector<int> v(in.begin(), in.end());
109 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
111 check_new_delete_called();
114 int a[] = {1, 2, 3, 4, 5};
115 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
116 std::vector<int, min_allocator<int> > v(in.begin(), in.end());
117 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
119 check_new_delete_called();
122 int a[] = {1, 2, 3, 4, 5};
123 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
124 std::vector<int, safe_allocator<int> > v(in.begin(), in.end());
125 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
127 check_new_delete_called();
130 int a[] = {1, 2, 3, 4, 5};
131 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
132 std::vector<int, test_allocator<int> > v(in.begin(), in.end());
133 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
135 check_new_delete_called();
138 std::vector<int> in(10, 42);
139 std::vector<int, limited_allocator<int, 100> > v(in.begin(), in.end());
140 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
142 check_new_delete_called();
144 #if TEST_STD_VER >= 23
146 std::vector<int> in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
147 std::vector<int, increasing_allocator<int>> v(in.begin(), in.end());
148 test_allocation_exception_for_strong_guarantee(v, in, v.max_size() + 1);
150 check_new_delete_called();
151 #endif
154 // Tests for std::bad_alloc during reallocation failures
157 std::vector<int> in(10, 42);
158 std::vector<int, limited_allocator<int, 100> > v(in.begin(), in.end());
159 test_allocation_exception_for_strong_guarantee(v, in, 91);
161 check_new_delete_called();
164 std::vector<int> in(10, 42);
165 std::vector<int, limited_allocator<int, 100> > v(in.begin(), in.end());
166 v.reserve(30);
167 test_allocation_exception_for_strong_guarantee(v, in, 61);
169 check_new_delete_called();
171 #if TEST_STD_VER >= 11
173 std::vector<MoveOnly> in(10);
174 std::vector<MoveOnly, limited_allocator<MoveOnly, 100> > v(10);
175 test_allocation_exception_for_strong_guarantee(v, in, 91);
177 check_new_delete_called();
180 std::vector<MoveOnly> in(10);
181 in.insert(in.cbegin() + 5, MoveOnly(42));
182 std::vector<MoveOnly, limited_allocator<MoveOnly, 100> > v(10);
183 v.reserve(30);
184 v.insert(v.cbegin() + 5, MoveOnly(42));
185 test_allocation_exception_for_strong_guarantee(v, in, 61);
187 check_new_delete_called();
188 #endif
190 { // Practical example: Testing with 100 integers.
191 auto in = getIntegerInputs(100);
192 std::vector<int, limited_allocator<int, 299> > v(in.begin(), in.end());
193 test_allocation_exception_for_strong_guarantee(v, in, 200);
195 check_new_delete_called();
197 { // Practical example: Testing with 100 strings, each 256 characters long.
198 std::vector<std::string> in = getStringInputsWithLength(100, 256);
199 std::vector<std::string, limited_allocator<std::string, 299> > v(in.begin(), in.end());
200 test_allocation_exception_for_strong_guarantee(v, in, 200);
202 check_new_delete_called();
205 // Check the strong exception guarantee during copy-constructor failures
206 void test_copy_ctor_exceptions() {
208 int a[] = {1, 2, 3, 4, 5};
209 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
210 std::vector<throwing_data<int> > v;
211 test_copy_ctor_exception_for_strong_guarantee(v, in);
213 check_new_delete_called();
216 int a[] = {1, 2, 3, 4, 5};
217 std::vector<int> in(a, a + sizeof(a) / sizeof(a[0]));
218 std::vector<throwing_data<int>, min_allocator<throwing_data<int> > > v;
219 test_copy_ctor_exception_for_strong_guarantee(v, in);
221 check_new_delete_called();
224 std::vector<int> in(10, 42);
225 std::vector<throwing_data<int>, safe_allocator<throwing_data<int> > > v;
226 test_copy_ctor_exception_for_strong_guarantee(v, in);
228 check_new_delete_called();
231 std::vector<int> in(10, 42);
232 std::vector<throwing_data<int>, test_allocator<throwing_data<int> > > v;
233 test_copy_ctor_exception_for_strong_guarantee(v, in);
235 check_new_delete_called();
238 std::vector<int> in(10, 42);
239 std::vector<throwing_data<int>, limited_allocator<throwing_data<int>, 100> > v;
240 test_copy_ctor_exception_for_strong_guarantee(v, in);
242 check_new_delete_called();
244 #if TEST_STD_VER >= 23
246 std::vector<int> in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
247 std::vector<throwing_data<int>, increasing_allocator<throwing_data<int>>> v;
248 test_copy_ctor_exception_for_strong_guarantee(v, in);
250 check_new_delete_called();
251 #endif
253 { // Practical example: Testing with 100 integers.
254 auto in = getIntegerInputs(100);
255 std::vector<throwing_data<int> > v;
256 test_copy_ctor_exception_for_strong_guarantee(v, in);
258 check_new_delete_called();
260 { // Practical example: Testing with 100 strings, each 256 characters long.
261 std::vector<std::string> in = getStringInputsWithLength(100, 256);
262 std::vector<throwing_data<std::string> > v;
263 test_copy_ctor_exception_for_strong_guarantee(v, in);
265 check_new_delete_called();
268 #if TEST_STD_VER >= 11
270 // Check that if T is Cpp17MoveInsertible && !Cpp17CopyInsertible, and T's move-ctor is not noexcept, then
271 // std::vector::reserve only provides basic guarantee.
272 void test_move_ctor_exceptions() {
274 std::vector<int> in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
275 std::vector<move_only_throwing_t<int>> v;
276 test_move_ctor_exception_for_basic_guarantee(v, in);
278 check_new_delete_called();
280 # if TEST_STD_VER >= 23
282 std::vector<int> in{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
283 std::vector<move_only_throwing_t<int>, increasing_allocator<move_only_throwing_t<int>>> v;
284 test_move_ctor_exception_for_basic_guarantee(v, in);
286 check_new_delete_called();
287 # endif
290 // Practical example: Testing with 100 strings, each 256 characters long.
291 std::vector<std::string> in = getStringInputsWithLength(100, 256);
292 std::vector<move_only_throwing_t<std::string> > v;
293 test_move_ctor_exception_for_basic_guarantee(v, in);
295 check_new_delete_called();
298 #endif
300 int main(int, char**) {
301 test_allocation_exceptions();
302 test_copy_ctor_exceptions();
303 #if TEST_STD_VER >= 11
304 test_move_ctor_exceptions();
305 #endif