xref: /llvm-project/llvm/unittests/ADT/BumpPtrListTest.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
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 
13 using namespace llvm;
14 
15 namespace {
16 
17 struct CountsDestructors {
18   static unsigned NumCalls;
~CountsDestructors__anonc0e900ed0111::CountsDestructors19   ~CountsDestructors() { ++NumCalls; }
20 };
21 unsigned CountsDestructors::NumCalls = 0;
22 
23 struct MoveOnly {
24   int V;
MoveOnly__anonc0e900ed0111::MoveOnly25   explicit MoveOnly(int V) : V(V) {}
26   MoveOnly() = delete;
MoveOnly__anonc0e900ed0111::MoveOnly27   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 
33 struct EmplaceOnly {
34   int V1, V2;
EmplaceOnly__anonc0e900ed0111::EmplaceOnly35   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 
TEST(BumpPtrListTest,DefaultConstructor)43 TEST(BumpPtrListTest, DefaultConstructor) {
44   BumpPtrList<int> L;
45   EXPECT_TRUE(L.empty());
46 }
47 
TEST(BumpPtrListTest,pushPopBack)48 TEST(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(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(Ns)) {
63     EXPECT_EQ(N, L.back());
64     L.pop_back();
65   }
66   EXPECT_TRUE(L.empty());
67 }
68 
TEST(BumpPtrListTest,pushPopFront)69 TEST(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(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(Ns)) {
84     EXPECT_EQ(N, L.front());
85     L.pop_front();
86   }
87   EXPECT_TRUE(L.empty());
88 }
89 
TEST(BumpPtrListTest,pushBackMoveOnly)90 TEST(BumpPtrListTest, pushBackMoveOnly) {
91   BumpPtrList<MoveOnly> L;
92   int Ns[] = {1, 3, 9, 5, 7};
93   for (const int N : Ns) {
94     L.push_back(MoveOnly(N));
95     EXPECT_EQ(N, L.back().V);
96   }
97   // Instantiate with MoveOnly.
98   while (!L.empty())
99     L.pop_back();
100 }
101 
TEST(BumpPtrListTest,pushFrontMoveOnly)102 TEST(BumpPtrListTest, pushFrontMoveOnly) {
103   BumpPtrList<MoveOnly> L;
104   int Ns[] = {1, 3, 9, 5, 7};
105   for (const int N : Ns) {
106     L.push_front(MoveOnly(N));
107     EXPECT_EQ(N, L.front().V);
108   }
109   // Instantiate with MoveOnly.
110   while (!L.empty())
111     L.pop_front();
112 }
113 
TEST(BumpPtrListTest,emplaceBack)114 TEST(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(N1s[I], 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 
TEST(BumpPtrListTest,emplaceFront)128 TEST(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(N1s[I], 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 
TEST(BumpPtrListTest,swap)142 TEST(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(L1.end(), std::begin(N1s), std::end(N1s));
149   {
150     BumpPtrList<int> L2;
151     L2.insert(L2.end(), std::begin(N2s), std::end(N2s));
152 
153     // Swap the lists.
154     L1.swap(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 
TEST(BumpPtrListTest,clear)171 TEST(BumpPtrListTest, clear) {
172   CountsDestructors::NumCalls = 0;
173   CountsDestructors N;
174   BumpPtrList<CountsDestructors> L;
175   L.push_back(N);
176   L.push_back(N);
177   L.push_back(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 
TEST(BumpPtrListTest,move)186 TEST(BumpPtrListTest, move) {
187   BumpPtrList<int> L1, L2;
188   L1.push_back(1);
189   L2.push_back(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 
TEST(BumpPtrListTest,moveCallsDestructors)196 TEST(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 
TEST(BumpPtrListTest,copy)205 TEST(BumpPtrListTest, copy) {
206   BumpPtrList<int> L1, L2;
207   L1.push_back(1);
208   L2.push_back(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 
TEST(BumpPtrListTest,copyCallsDestructors)216 TEST(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 
TEST(BumpPtrListTest,resetAlloc)225 TEST(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(5);
232   L.erase(L.begin());
233   L.resetAlloc();
234 
235   // Resetting a non-empty list should crash.
236   L.push_back(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