1 //===- unittests/ADT/BumpPtrListTest.cpp - BumpPtrList unit tests ---------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/AllocatorList.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "gtest/gtest.h"
17 struct CountsDestructors
{
18 static unsigned NumCalls
;
19 ~CountsDestructors() { ++NumCalls
; }
21 unsigned CountsDestructors::NumCalls
= 0;
25 explicit MoveOnly(int V
) : V(V
) {}
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;
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;
43 TEST(BumpPtrListTest
, DefaultConstructor
) {
45 EXPECT_TRUE(L
.empty());
48 TEST(BumpPtrListTest
, pushPopBack
) {
49 // Build a list with push_back.
51 int Ns
[] = {1, 3, 9, 5, 7};
52 for (const int N
: Ns
)
55 // Use iterators to check contents.
59 EXPECT_EQ(I
, L
.end());
61 // Unbuild the list with pop_back.
62 for (int N
: llvm::reverse(Ns
)) {
63 EXPECT_EQ(N
, L
.back());
66 EXPECT_TRUE(L
.empty());
69 TEST(BumpPtrListTest
, pushPopFront
) {
70 // Build a list with push_front.
72 int Ns
[] = {1, 3, 9, 5, 7};
73 for (const int N
: Ns
)
76 // Use reverse iterators to check contents.
80 EXPECT_EQ(I
, L
.rend());
82 // Unbuild the list with pop_front.
83 for (int N
: llvm::reverse(Ns
)) {
84 EXPECT_EQ(N
, L
.front());
87 EXPECT_TRUE(L
.empty());
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
);
97 // Instantiate with MoveOnly.
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
);
109 // Instantiate with MoveOnly.
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
);
123 // Instantiate with EmplaceOnly.
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
);
137 // Instantiate with EmplaceOnly.
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};
148 L1
.insert(L1
.end(), std::begin(N1s
), std::end(N1s
));
151 L2
.insert(L2
.end(), std::begin(N2s
), std::end(N2s
));
156 // Check L2's contents before it goes out of scope.
160 EXPECT_EQ(I
, L2
.end());
163 // Check L1's contents now that L2 is out of scope (with its allocation
168 EXPECT_EQ(I
, L1
.end());
171 TEST(BumpPtrListTest
, clear
) {
172 CountsDestructors::NumCalls
= 0;
174 BumpPtrList
<CountsDestructors
> L
;
178 EXPECT_EQ(3u, L
.size());
179 EXPECT_EQ(0u, CountsDestructors::NumCalls
);
181 EXPECT_EQ(1u, CountsDestructors::NumCalls
);
183 EXPECT_EQ(3u, CountsDestructors::NumCalls
);
186 TEST(BumpPtrListTest
, move
) {
187 BumpPtrList
<int> L1
, L2
;
191 EXPECT_EQ(1u, L1
.size());
192 EXPECT_EQ(2, L1
.front());
193 EXPECT_EQ(0u, L2
.size());
196 TEST(BumpPtrListTest
, moveCallsDestructors
) {
197 CountsDestructors::NumCalls
= 0;
198 BumpPtrList
<CountsDestructors
> L1
, L2
;
200 EXPECT_EQ(0u, CountsDestructors::NumCalls
);
202 EXPECT_EQ(1u, CountsDestructors::NumCalls
);
205 TEST(BumpPtrListTest
, copy
) {
206 BumpPtrList
<int> 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());
216 TEST(BumpPtrListTest
, copyCallsDestructors
) {
217 CountsDestructors::NumCalls
= 0;
218 BumpPtrList
<CountsDestructors
> L1
, L2
;
220 EXPECT_EQ(0u, CountsDestructors::NumCalls
);
222 EXPECT_EQ(1u, CountsDestructors::NumCalls
);
225 TEST(BumpPtrListTest
, resetAlloc
) {
226 // Resetting an empty list should work.
229 // Resetting an empty list that has allocated should also work.
235 // Resetting a non-empty list should crash.
237 #if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
238 EXPECT_DEATH(L
.resetAlloc(), "Cannot reset allocator if not empty");