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
23struct 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
34bool Throws::sThrows = false;
35#endif
36
37TEST_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
167int 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

source code of libcxx/test/std/containers/sequences/vector/vector.modifiers/erase_iter_iter.pass.cpp