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 | // <vector> |
10 | |
11 | // iterator erase(const_iterator first, const_iterator last); |
12 | |
13 | #include <vector> |
14 | #include <iterator> |
15 | #include <cassert> |
16 | |
17 | #include "asan_testing.h" |
18 | #include "min_allocator.h" |
19 | #include "MoveOnly.h" |
20 | #include "test_macros.h" |
21 | |
22 | #ifndef TEST_HAS_NO_EXCEPTIONS |
23 | struct Throws { |
24 | Throws() : v_(0) {} |
25 | Throws(int v) : v_(v) {} |
26 | Throws(const Throws &rhs) : v_(rhs.v_) { if (sThrows) throw 1; } |
27 | Throws( Throws &&rhs) : v_(rhs.v_) { if (sThrows) throw 1; } |
28 | Throws& operator=(const Throws &rhs) { v_ = rhs.v_; return *this; } |
29 | Throws& operator=( Throws &&rhs) { v_ = rhs.v_; return *this; } |
30 | int v_; |
31 | static bool sThrows; |
32 | }; |
33 | |
34 | bool Throws::sThrows = false; |
35 | #endif |
36 | |
37 | TEST_CONSTEXPR_CXX20 bool tests() |
38 | { |
39 | int a1[] = {1, 2, 3}; |
40 | { |
41 | std::vector<int> l1(a1, a1+3); |
42 | assert(is_contiguous_container_asan_correct(l1)); |
43 | std::vector<int>::iterator i = l1.erase(first: l1.cbegin(), last: l1.cbegin()); |
44 | assert(l1.size() == 3); |
45 | assert(std::distance(l1.cbegin(), l1.cend()) == 3); |
46 | assert(i == l1.begin()); |
47 | assert(is_contiguous_container_asan_correct(l1)); |
48 | } |
49 | { |
50 | std::vector<int> l1(a1, a1+3); |
51 | assert(is_contiguous_container_asan_correct(l1)); |
52 | std::vector<int>::iterator i = l1.erase(first: l1.cbegin(), last: std::next(x: l1.cbegin())); |
53 | assert(l1.size() == 2); |
54 | assert(std::distance(l1.cbegin(), l1.cend()) == 2); |
55 | assert(i == l1.begin()); |
56 | assert(l1 == std::vector<int>(a1+1, a1+3)); |
57 | assert(is_contiguous_container_asan_correct(l1)); |
58 | } |
59 | { |
60 | std::vector<int> l1(a1, a1+3); |
61 | assert(is_contiguous_container_asan_correct(l1)); |
62 | std::vector<int>::iterator i = l1.erase(first: l1.cbegin(), last: std::next(x: l1.cbegin(), n: 2)); |
63 | assert(l1.size() == 1); |
64 | assert(std::distance(l1.cbegin(), l1.cend()) == 1); |
65 | assert(i == l1.begin()); |
66 | assert(l1 == std::vector<int>(a1+2, a1+3)); |
67 | assert(is_contiguous_container_asan_correct(l1)); |
68 | } |
69 | { |
70 | std::vector<int> l1(a1, a1+3); |
71 | assert(is_contiguous_container_asan_correct(l1)); |
72 | std::vector<int>::iterator i = l1.erase(first: l1.cbegin(), last: std::next(x: l1.cbegin(), n: 3)); |
73 | assert(l1.size() == 0); |
74 | assert(std::distance(l1.cbegin(), l1.cend()) == 0); |
75 | assert(i == l1.begin()); |
76 | assert(is_contiguous_container_asan_correct(l1)); |
77 | } |
78 | { |
79 | std::vector<std::vector<int> > outer(2, std::vector<int>(1)); |
80 | assert(is_contiguous_container_asan_correct(outer)); |
81 | assert(is_contiguous_container_asan_correct(outer[0])); |
82 | assert(is_contiguous_container_asan_correct(outer[1])); |
83 | outer.erase(first: outer.begin(), last: outer.begin()); |
84 | assert(outer.size() == 2); |
85 | assert(outer[0].size() == 1); |
86 | assert(outer[1].size() == 1); |
87 | assert(is_contiguous_container_asan_correct(outer)); |
88 | assert(is_contiguous_container_asan_correct(outer[0])); |
89 | assert(is_contiguous_container_asan_correct(outer[1])); |
90 | } |
91 | // Make sure vector::erase works with move-only types |
92 | { |
93 | // When non-trivial |
94 | { |
95 | std::vector<MoveOnly> v; |
96 | v.emplace_back(1); v.emplace_back(2); v.emplace_back(3); |
97 | v.erase(v.begin(), v.begin() + 2); |
98 | assert(v.size() == 1); |
99 | assert(v[0] == MoveOnly(3)); |
100 | } |
101 | // When trivial |
102 | { |
103 | std::vector<TrivialMoveOnly> v; |
104 | v.emplace_back(1); v.emplace_back(2); v.emplace_back(3); |
105 | v.erase(v.begin(), v.begin() + 2); |
106 | assert(v.size() == 1); |
107 | assert(v[0] == TrivialMoveOnly(3)); |
108 | } |
109 | } |
110 | #if TEST_STD_VER >= 11 |
111 | { |
112 | std::vector<int, min_allocator<int>> l1(a1, a1+3); |
113 | assert(is_contiguous_container_asan_correct(l1)); |
114 | std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), l1.cbegin()); |
115 | assert(l1.size() == 3); |
116 | assert(std::distance(l1.cbegin(), l1.cend()) == 3); |
117 | assert(i == l1.begin()); |
118 | assert(is_contiguous_container_asan_correct(l1)); |
119 | } |
120 | { |
121 | std::vector<int, min_allocator<int>> l1(a1, a1+3); |
122 | assert(is_contiguous_container_asan_correct(l1)); |
123 | std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin())); |
124 | assert(l1.size() == 2); |
125 | assert(std::distance(l1.cbegin(), l1.cend()) == 2); |
126 | assert(i == l1.begin()); |
127 | assert((l1 == std::vector<int, min_allocator<int>>(a1+1, a1+3))); |
128 | assert(is_contiguous_container_asan_correct(l1)); |
129 | } |
130 | { |
131 | std::vector<int, min_allocator<int>> l1(a1, a1+3); |
132 | assert(is_contiguous_container_asan_correct(l1)); |
133 | std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 2)); |
134 | assert(l1.size() == 1); |
135 | assert(std::distance(l1.cbegin(), l1.cend()) == 1); |
136 | assert(i == l1.begin()); |
137 | assert((l1 == std::vector<int, min_allocator<int>>(a1+2, a1+3))); |
138 | assert(is_contiguous_container_asan_correct(l1)); |
139 | } |
140 | { |
141 | std::vector<int, min_allocator<int>> l1(a1, a1+3); |
142 | assert(is_contiguous_container_asan_correct(l1)); |
143 | std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 3)); |
144 | assert(l1.size() == 0); |
145 | assert(std::distance(l1.cbegin(), l1.cend()) == 0); |
146 | assert(i == l1.begin()); |
147 | assert(is_contiguous_container_asan_correct(l1)); |
148 | } |
149 | { |
150 | std::vector<std::vector<int, min_allocator<int>>, min_allocator<std::vector<int, min_allocator<int>>>> outer(2, std::vector<int, min_allocator<int>>(1)); |
151 | assert(is_contiguous_container_asan_correct(outer)); |
152 | assert(is_contiguous_container_asan_correct(outer[0])); |
153 | assert(is_contiguous_container_asan_correct(outer[1])); |
154 | outer.erase(outer.begin(), outer.begin()); |
155 | assert(outer.size() == 2); |
156 | assert(outer[0].size() == 1); |
157 | assert(outer[1].size() == 1); |
158 | assert(is_contiguous_container_asan_correct(outer)); |
159 | assert(is_contiguous_container_asan_correct(outer[0])); |
160 | assert(is_contiguous_container_asan_correct(outer[1])); |
161 | } |
162 | #endif |
163 | |
164 | return true; |
165 | } |
166 | |
167 | int main(int, char**) |
168 | { |
169 | tests(); |
170 | #if TEST_STD_VER > 17 |
171 | static_assert(tests()); |
172 | #endif |
173 | |
174 | #ifndef TEST_HAS_NO_EXCEPTIONS |
175 | // Test for LWG2853: |
176 | // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T. |
177 | { |
178 | Throws arr[] = {1, 2, 3}; |
179 | std::vector<Throws> v(arr, arr+3); |
180 | Throws::sThrows = true; |
181 | v.erase(first: v.begin(), last: --v.end()); |
182 | assert(v.size() == 1); |
183 | v.erase(first: v.begin(), last: v.end()); |
184 | assert(v.size() == 0); |
185 | } |
186 | #endif |
187 | |
188 | return 0; |
189 | } |
190 | |