1//===- unittests/ADT/BumpPtrListTest.cpp - BumpPtrList unit tests ---------===//
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#include "llvm/ADT/AllocatorList.h"
10#include "llvm/ADT/STLExtras.h"
11#include "gtest/gtest.h"
12
13using namespace llvm;
14
15namespace {
16
17struct CountsDestructors {
18 static unsigned NumCalls;
19 ~CountsDestructors() { ++NumCalls; }
20};
21unsigned CountsDestructors::NumCalls = 0;
22
23struct MoveOnly {
24 int V;
25 explicit MoveOnly(int V) : V(V) {}
26 MoveOnly() = delete;
27 MoveOnly(MoveOnly &&X) { V = X.V; }
28 MoveOnly(const MoveOnly &X) = delete;
29 MoveOnly &operator=(MoveOnly &&X) = delete;
30 MoveOnly &operator=(const MoveOnly &X) = delete;
31};
32
33struct EmplaceOnly {
34 int V1, V2;
35 explicit EmplaceOnly(int V1, int V2) : V1(V1), V2(V2) {}
36 EmplaceOnly() = delete;
37 EmplaceOnly(EmplaceOnly &&X) = delete;
38 EmplaceOnly(const EmplaceOnly &X) = delete;
39 EmplaceOnly &operator=(EmplaceOnly &&X) = delete;
40 EmplaceOnly &operator=(const EmplaceOnly &X) = delete;
41};
42
43TEST(BumpPtrListTest, DefaultConstructor) {
44 BumpPtrList<int> L;
45 EXPECT_TRUE(L.empty());
46}
47
48TEST(BumpPtrListTest, pushPopBack) {
49 // Build a list with push_back.
50 BumpPtrList<int> L;
51 int Ns[] = {1, 3, 9, 5, 7};
52 for (const int N : Ns)
53 L.push_back(V: N);
54
55 // Use iterators to check contents.
56 auto I = L.begin();
57 for (int N : Ns)
58 EXPECT_EQ(N, *I++);
59 EXPECT_EQ(I, L.end());
60
61 // Unbuild the list with pop_back.
62 for (int N : llvm::reverse(C&: Ns)) {
63 EXPECT_EQ(N, L.back());
64 L.pop_back();
65 }
66 EXPECT_TRUE(L.empty());
67}
68
69TEST(BumpPtrListTest, pushPopFront) {
70 // Build a list with push_front.
71 BumpPtrList<int> L;
72 int Ns[] = {1, 3, 9, 5, 7};
73 for (const int N : Ns)
74 L.push_front(V: N);
75
76 // Use reverse iterators to check contents.
77 auto I = L.rbegin();
78 for (int N : Ns)
79 EXPECT_EQ(N, *I++);
80 EXPECT_EQ(I, L.rend());
81
82 // Unbuild the list with pop_front.
83 for (int N : llvm::reverse(C&: Ns)) {
84 EXPECT_EQ(N, L.front());
85 L.pop_front();
86 }
87 EXPECT_TRUE(L.empty());
88}
89
90TEST(BumpPtrListTest, pushBackMoveOnly) {
91 BumpPtrList<MoveOnly> L;
92 int Ns[] = {1, 3, 9, 5, 7};
93 for (const int N : Ns) {
94 L.push_back(V: MoveOnly(N));
95 EXPECT_EQ(N, L.back().V);
96 }
97 // Instantiate with MoveOnly.
98 while (!L.empty())
99 L.pop_back();
100}
101
102TEST(BumpPtrListTest, pushFrontMoveOnly) {
103 BumpPtrList<MoveOnly> L;
104 int Ns[] = {1, 3, 9, 5, 7};
105 for (const int N : Ns) {
106 L.push_front(V: MoveOnly(N));
107 EXPECT_EQ(N, L.front().V);
108 }
109 // Instantiate with MoveOnly.
110 while (!L.empty())
111 L.pop_front();
112}
113
114TEST(BumpPtrListTest, emplaceBack) {
115 BumpPtrList<EmplaceOnly> L;
116 int N1s[] = {1, 3, 9, 5, 7};
117 int N2s[] = {7, 3, 1, 8, 2};
118 for (int I = 0; I != 5; ++I) {
119 L.emplace_back(Vs&: N1s[I], Vs&: N2s[I]);
120 EXPECT_EQ(N1s[I], L.back().V1);
121 EXPECT_EQ(N2s[I], L.back().V2);
122 }
123 // Instantiate with EmplaceOnly.
124 while (!L.empty())
125 L.pop_back();
126}
127
128TEST(BumpPtrListTest, emplaceFront) {
129 BumpPtrList<EmplaceOnly> L;
130 int N1s[] = {1, 3, 9, 5, 7};
131 int N2s[] = {7, 3, 1, 8, 2};
132 for (int I = 0; I != 5; ++I) {
133 L.emplace_front(Vs&: N1s[I], Vs&: N2s[I]);
134 EXPECT_EQ(N1s[I], L.front().V1);
135 EXPECT_EQ(N2s[I], L.front().V2);
136 }
137 // Instantiate with EmplaceOnly.
138 while (!L.empty())
139 L.pop_front();
140}
141
142TEST(BumpPtrListTest, swap) {
143 // Build two lists with different lifetimes and swap them.
144 int N1s[] = {1, 3, 5, 7, 9};
145 int N2s[] = {2, 4, 6, 8, 10};
146
147 BumpPtrList<int> L1;
148 L1.insert(I: L1.end(), First: std::begin(arr&: N1s), Last: std::end(arr&: N1s));
149 {
150 BumpPtrList<int> L2;
151 L2.insert(I: L2.end(), First: std::begin(arr&: N2s), Last: std::end(arr&: N2s));
152
153 // Swap the lists.
154 L1.swap(RHS&: L2);
155
156 // Check L2's contents before it goes out of scope.
157 auto I = L2.begin();
158 for (int N : N1s)
159 EXPECT_EQ(N, *I++);
160 EXPECT_EQ(I, L2.end());
161 }
162
163 // Check L1's contents now that L2 is out of scope (with its allocation
164 // blocks).
165 auto I = L1.begin();
166 for (int N : N2s)
167 EXPECT_EQ(N, *I++);
168 EXPECT_EQ(I, L1.end());
169}
170
171TEST(BumpPtrListTest, clear) {
172 CountsDestructors::NumCalls = 0;
173 CountsDestructors N;
174 BumpPtrList<CountsDestructors> L;
175 L.push_back(V: N);
176 L.push_back(V: N);
177 L.push_back(V: N);
178 EXPECT_EQ(3u, L.size());
179 EXPECT_EQ(0u, CountsDestructors::NumCalls);
180 L.pop_back();
181 EXPECT_EQ(1u, CountsDestructors::NumCalls);
182 L.clear();
183 EXPECT_EQ(3u, CountsDestructors::NumCalls);
184}
185
186TEST(BumpPtrListTest, move) {
187 BumpPtrList<int> L1, L2;
188 L1.push_back(V: 1);
189 L2.push_back(V: 2);
190 L1 = std::move(L2);
191 EXPECT_EQ(1u, L1.size());
192 EXPECT_EQ(2, L1.front());
193 EXPECT_EQ(0u, L2.size());
194}
195
196TEST(BumpPtrListTest, moveCallsDestructors) {
197 CountsDestructors::NumCalls = 0;
198 BumpPtrList<CountsDestructors> L1, L2;
199 L1.emplace_back();
200 EXPECT_EQ(0u, CountsDestructors::NumCalls);
201 L1 = std::move(L2);
202 EXPECT_EQ(1u, CountsDestructors::NumCalls);
203}
204
205TEST(BumpPtrListTest, copy) {
206 BumpPtrList<int> L1, L2;
207 L1.push_back(V: 1);
208 L2.push_back(V: 2);
209 L1 = L2;
210 EXPECT_EQ(1u, L1.size());
211 EXPECT_EQ(2, L1.front());
212 EXPECT_EQ(1u, L2.size());
213 EXPECT_EQ(2, L2.front());
214}
215
216TEST(BumpPtrListTest, copyCallsDestructors) {
217 CountsDestructors::NumCalls = 0;
218 BumpPtrList<CountsDestructors> L1, L2;
219 L1.emplace_back();
220 EXPECT_EQ(0u, CountsDestructors::NumCalls);
221 L1 = L2;
222 EXPECT_EQ(1u, CountsDestructors::NumCalls);
223}
224
225TEST(BumpPtrListTest, resetAlloc) {
226 // Resetting an empty list should work.
227 BumpPtrList<int> L;
228
229 // Resetting an empty list that has allocated should also work.
230 L.resetAlloc();
231 L.push_back(V: 5);
232 L.erase(I: L.begin());
233 L.resetAlloc();
234
235 // Resetting a non-empty list should crash.
236 L.push_back(V: 5);
237#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
238 EXPECT_DEATH(L.resetAlloc(), "Cannot reset allocator if not empty");
239#endif
240}
241
242} // end namespace
243

source code of llvm/unittests/ADT/BumpPtrListTest.cpp