1 | //===- llvm/unittest/ADT/ArrayRefTest.cpp - ArrayRef 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/ArrayRef.h" |
10 | #include "llvm/Support/Allocator.h" |
11 | #include "llvm/Support/raw_ostream.h" |
12 | #include "gtest/gtest.h" |
13 | #include <limits> |
14 | #include <vector> |
15 | using namespace llvm; |
16 | |
17 | // Check that the ArrayRef-of-pointer converting constructor only allows adding |
18 | // cv qualifiers (not removing them, or otherwise changing the type) |
19 | static_assert(std::is_convertible_v<ArrayRef<int *>, ArrayRef<const int *>>, |
20 | "Adding const" ); |
21 | static_assert(std::is_convertible_v<ArrayRef<int *>, ArrayRef<volatile int *>>, |
22 | "Adding volatile" ); |
23 | static_assert(!std::is_convertible_v<ArrayRef<int *>, ArrayRef<float *>>, |
24 | "Changing pointer of one type to a pointer of another" ); |
25 | static_assert(!std::is_convertible_v<ArrayRef<const int *>, ArrayRef<int *>>, |
26 | "Removing const" ); |
27 | static_assert(!std::is_convertible_v<ArrayRef<volatile int *>, ArrayRef<int *>>, |
28 | "Removing volatile" ); |
29 | |
30 | // Check that we can't accidentally assign a temporary location to an ArrayRef. |
31 | // (Unfortunately we can't make use of the same thing with constructors.) |
32 | static_assert(!std::is_assignable_v<ArrayRef<int *> &, int *>, |
33 | "Assigning from single prvalue element" ); |
34 | static_assert(!std::is_assignable_v<ArrayRef<int *> &, int *&&>, |
35 | "Assigning from single xvalue element" ); |
36 | static_assert(std::is_assignable_v<ArrayRef<int *> &, int *&>, |
37 | "Assigning from single lvalue element" ); |
38 | static_assert( |
39 | !std::is_assignable_v<ArrayRef<int *> &, std::initializer_list<int *>>, |
40 | "Assigning from an initializer list" ); |
41 | |
42 | namespace { |
43 | |
44 | TEST(ArrayRefTest, AllocatorCopy) { |
45 | BumpPtrAllocator Alloc; |
46 | static const uint16_t Words1[] = { 1, 4, 200, 37 }; |
47 | ArrayRef<uint16_t> Array1 = ArrayRef(Words1, 4); |
48 | static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 }; |
49 | ArrayRef<uint16_t> Array2 = ArrayRef(Words2, 5); |
50 | ArrayRef<uint16_t> Array1c = Array1.copy(A&: Alloc); |
51 | ArrayRef<uint16_t> Array2c = Array2.copy(A&: Alloc); |
52 | EXPECT_TRUE(Array1.equals(Array1c)); |
53 | EXPECT_NE(Array1.data(), Array1c.data()); |
54 | EXPECT_TRUE(Array2.equals(Array2c)); |
55 | EXPECT_NE(Array2.data(), Array2c.data()); |
56 | |
57 | // Check that copy can cope with uninitialized memory. |
58 | struct NonAssignable { |
59 | const char *Ptr; |
60 | |
61 | NonAssignable(const char *Ptr) : Ptr(Ptr) {} |
62 | NonAssignable(const NonAssignable &RHS) = default; |
63 | void operator=(const NonAssignable &RHS) { assert(RHS.Ptr != nullptr); } |
64 | bool operator==(const NonAssignable &RHS) const { return Ptr == RHS.Ptr; } |
65 | } Array3Src[] = {"hello" , "world" }; |
66 | ArrayRef<NonAssignable> Array3Copy = ArrayRef(Array3Src).copy(A&: Alloc); |
67 | EXPECT_EQ(ArrayRef(Array3Src), Array3Copy); |
68 | EXPECT_NE(ArrayRef(Array3Src).data(), Array3Copy.data()); |
69 | } |
70 | |
71 | // This test is pure UB given the ArrayRef<> implementation. |
72 | // You are not allowed to produce non-null pointers given null base pointer. |
73 | TEST(ArrayRefTest, DISABLED_SizeTSizedOperations) { |
74 | ArrayRef<char> AR(nullptr, std::numeric_limits<ptrdiff_t>::max()); |
75 | |
76 | // Check that drop_back accepts size_t-sized numbers. |
77 | EXPECT_EQ(1U, AR.drop_back(AR.size() - 1).size()); |
78 | |
79 | // Check that drop_front accepts size_t-sized numbers. |
80 | EXPECT_EQ(1U, AR.drop_front(AR.size() - 1).size()); |
81 | |
82 | // Check that slice accepts size_t-sized numbers. |
83 | EXPECT_EQ(1U, AR.slice(AR.size() - 1).size()); |
84 | EXPECT_EQ(AR.size() - 1, AR.slice(1, AR.size() - 1).size()); |
85 | } |
86 | |
87 | TEST(ArrayRefTest, DropBack) { |
88 | static const int TheNumbers[] = {4, 8, 15, 16, 23, 42}; |
89 | ArrayRef<int> AR1(TheNumbers); |
90 | ArrayRef<int> AR2(TheNumbers, AR1.size() - 1); |
91 | EXPECT_TRUE(AR1.drop_back().equals(AR2)); |
92 | } |
93 | |
94 | TEST(ArrayRefTest, DropFront) { |
95 | static const int TheNumbers[] = {4, 8, 15, 16, 23, 42}; |
96 | ArrayRef<int> AR1(TheNumbers); |
97 | ArrayRef<int> AR2(&TheNumbers[2], AR1.size() - 2); |
98 | EXPECT_TRUE(AR1.drop_front(2).equals(AR2)); |
99 | } |
100 | |
101 | TEST(ArrayRefTest, DropWhile) { |
102 | static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; |
103 | ArrayRef<int> AR1(TheNumbers); |
104 | ArrayRef<int> Expected = AR1.drop_front(N: 3); |
105 | EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 == 1; })); |
106 | |
107 | EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; })); |
108 | EXPECT_EQ(ArrayRef<int>(), |
109 | AR1.drop_while([](const int &N) { return N > 0; })); |
110 | } |
111 | |
112 | TEST(ArrayRefTest, DropUntil) { |
113 | static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; |
114 | ArrayRef<int> AR1(TheNumbers); |
115 | ArrayRef<int> Expected = AR1.drop_front(N: 3); |
116 | EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 == 0; })); |
117 | |
118 | EXPECT_EQ(ArrayRef<int>(), |
119 | AR1.drop_until([](const int &N) { return N < 0; })); |
120 | EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; })); |
121 | } |
122 | |
123 | TEST(ArrayRefTest, TakeBack) { |
124 | static const int TheNumbers[] = {4, 8, 15, 16, 23, 42}; |
125 | ArrayRef<int> AR1(TheNumbers); |
126 | ArrayRef<int> AR2(AR1.end() - 1, 1); |
127 | EXPECT_TRUE(AR1.take_back().equals(AR2)); |
128 | } |
129 | |
130 | TEST(ArrayRefTest, TakeFront) { |
131 | static const int TheNumbers[] = {4, 8, 15, 16, 23, 42}; |
132 | ArrayRef<int> AR1(TheNumbers); |
133 | ArrayRef<int> AR2(AR1.data(), 2); |
134 | EXPECT_TRUE(AR1.take_front(2).equals(AR2)); |
135 | } |
136 | |
137 | TEST(ArrayRefTest, TakeWhile) { |
138 | static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; |
139 | ArrayRef<int> AR1(TheNumbers); |
140 | ArrayRef<int> Expected = AR1.take_front(N: 3); |
141 | EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 == 1; })); |
142 | |
143 | EXPECT_EQ(ArrayRef<int>(), |
144 | AR1.take_while([](const int &N) { return N < 0; })); |
145 | EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; })); |
146 | } |
147 | |
148 | TEST(ArrayRefTest, TakeUntil) { |
149 | static const int TheNumbers[] = {1, 3, 5, 8, 10, 11}; |
150 | ArrayRef<int> AR1(TheNumbers); |
151 | ArrayRef<int> Expected = AR1.take_front(N: 3); |
152 | EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 == 0; })); |
153 | |
154 | EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; })); |
155 | EXPECT_EQ(ArrayRef<int>(), |
156 | AR1.take_until([](const int &N) { return N > 0; })); |
157 | } |
158 | |
159 | TEST(ArrayRefTest, Equals) { |
160 | static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8}; |
161 | ArrayRef<int> AR1(A1); |
162 | EXPECT_TRUE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8})); |
163 | EXPECT_FALSE(AR1.equals({8, 1, 2, 4, 5, 6, 6, 7})); |
164 | EXPECT_FALSE(AR1.equals({2, 4, 5, 6, 6, 7, 8, 1})); |
165 | EXPECT_FALSE(AR1.equals({0, 1, 2, 4, 5, 6, 6, 7})); |
166 | EXPECT_FALSE(AR1.equals({1, 2, 42, 4, 5, 6, 7, 8})); |
167 | EXPECT_FALSE(AR1.equals({42, 2, 3, 4, 5, 6, 7, 8})); |
168 | EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 42})); |
169 | EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7})); |
170 | EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8, 9})); |
171 | |
172 | ArrayRef<int> AR1a = AR1.drop_back(); |
173 | EXPECT_TRUE(AR1a.equals({1, 2, 3, 4, 5, 6, 7})); |
174 | EXPECT_FALSE(AR1a.equals({1, 2, 3, 4, 5, 6, 7, 8})); |
175 | |
176 | ArrayRef<int> AR1b = AR1a.slice(N: 2, M: 4); |
177 | EXPECT_TRUE(AR1b.equals({3, 4, 5, 6})); |
178 | EXPECT_FALSE(AR1b.equals({2, 3, 4, 5, 6})); |
179 | EXPECT_FALSE(AR1b.equals({3, 4, 5, 6, 7})); |
180 | } |
181 | |
182 | TEST(ArrayRefTest, EmptyEquals) { |
183 | EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>()); |
184 | } |
185 | |
186 | TEST(ArrayRefTest, ConstConvert) { |
187 | int buf[4]; |
188 | for (int i = 0; i < 4; ++i) |
189 | buf[i] = i; |
190 | |
191 | static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]}; |
192 | ArrayRef<const int *> a((ArrayRef<int *>(A))); |
193 | a = ArrayRef<int *>(A); |
194 | } |
195 | |
196 | static std::vector<int> ReturnTest12() { return {1, 2}; } |
197 | static void ArgTest12(ArrayRef<int> A) { |
198 | EXPECT_EQ(2U, A.size()); |
199 | EXPECT_EQ(1, A[0]); |
200 | EXPECT_EQ(2, A[1]); |
201 | } |
202 | |
203 | TEST(ArrayRefTest, InitializerList) { |
204 | std::initializer_list<int> init_list = { 0, 1, 2, 3, 4 }; |
205 | ArrayRef<int> A = init_list; |
206 | for (int i = 0; i < 5; ++i) |
207 | EXPECT_EQ(i, A[i]); |
208 | |
209 | std::vector<int> B = ReturnTest12(); |
210 | A = B; |
211 | EXPECT_EQ(1, A[0]); |
212 | EXPECT_EQ(2, A[1]); |
213 | |
214 | ArgTest12(A: {1, 2}); |
215 | } |
216 | |
217 | TEST(ArrayRefTest, EmptyInitializerList) { |
218 | ArrayRef<int> A = {}; |
219 | EXPECT_TRUE(A.empty()); |
220 | |
221 | A = {}; |
222 | EXPECT_TRUE(A.empty()); |
223 | } |
224 | |
225 | TEST(ArrayRefTest, ArrayRef) { |
226 | static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8}; |
227 | |
228 | // A copy is expected for non-const ArrayRef (thin copy) |
229 | ArrayRef<int> AR1(A1); |
230 | const ArrayRef<int> &AR1Ref = ArrayRef(AR1); |
231 | EXPECT_NE(&AR1, &AR1Ref); |
232 | EXPECT_TRUE(AR1.equals(AR1Ref)); |
233 | |
234 | // A copy is expected for non-const ArrayRef (thin copy) |
235 | const ArrayRef<int> AR2(A1); |
236 | const ArrayRef<int> &AR2Ref = ArrayRef(AR2); |
237 | EXPECT_NE(&AR2Ref, &AR2); |
238 | EXPECT_TRUE(AR2.equals(AR2Ref)); |
239 | } |
240 | |
241 | TEST(ArrayRefTest, OwningArrayRef) { |
242 | static const int A1[] = {0, 1}; |
243 | OwningArrayRef<int> A{ArrayRef(A1)}; |
244 | OwningArrayRef<int> B(std::move(A)); |
245 | EXPECT_EQ(A.data(), nullptr); |
246 | } |
247 | |
248 | TEST(ArrayRefTest, ArrayRefFromStdArray) { |
249 | std::array<int, 5> A1{._M_elems: {42, -5, 0, 1000000, -1000000}}; |
250 | ArrayRef<int> A2 = ArrayRef(A1); |
251 | |
252 | EXPECT_EQ(A1.size(), A2.size()); |
253 | for (std::size_t i = 0; i < A1.size(); ++i) { |
254 | EXPECT_EQ(A1[i], A2[i]); |
255 | } |
256 | } |
257 | |
258 | static_assert(std::is_trivially_copyable_v<ArrayRef<int>>, |
259 | "trivially copyable" ); |
260 | |
261 | TEST(ArrayRefTest, MutableArrayRefDeductionGuides) { |
262 | // Single element |
263 | { |
264 | int x = 0; |
265 | auto aref = MutableArrayRef(x); |
266 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
267 | EXPECT_EQ(aref.data(), &x); |
268 | EXPECT_EQ(aref.size(), 1u); |
269 | |
270 | // Make sure it's mutable still |
271 | aref[0] = 1; |
272 | EXPECT_EQ(x, 1); |
273 | } |
274 | |
275 | // Pointer + length |
276 | { |
277 | int x[] = {0, 1, 2, 3}; |
278 | auto aref = MutableArrayRef(&x[0], 4); |
279 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
280 | EXPECT_EQ(aref.data(), &x[0]); |
281 | EXPECT_EQ(aref.size(), 4u); |
282 | } |
283 | |
284 | // // Pointer + pointer |
285 | { |
286 | int x[] = {0, 1, 2, 3}; |
287 | auto aref = MutableArrayRef(std::begin(arr&: x), std::end(arr&: x)); |
288 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
289 | EXPECT_EQ(aref.data(), &x[0]); |
290 | EXPECT_EQ(aref.size(), 4u); |
291 | } |
292 | |
293 | // SmallVector |
294 | { |
295 | SmallVector<int> sv1; |
296 | SmallVectorImpl<int> &sv2 = sv1; |
297 | sv1.resize(N: 5); |
298 | auto aref1 = MutableArrayRef(sv1); |
299 | auto aref2 = MutableArrayRef(sv2); |
300 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref1)>); |
301 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>); |
302 | EXPECT_EQ(aref1.data(), sv1.data()); |
303 | EXPECT_EQ(aref1.size(), sv1.size()); |
304 | EXPECT_EQ(aref2.data(), sv2.data()); |
305 | EXPECT_EQ(aref2.size(), sv2.size()); |
306 | } |
307 | |
308 | // std::vector |
309 | { |
310 | std::vector<int> x(5); |
311 | auto aref = MutableArrayRef(x); |
312 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
313 | EXPECT_EQ(aref.data(), x.data()); |
314 | EXPECT_EQ(aref.size(), x.size()); |
315 | } |
316 | |
317 | // std::array |
318 | { |
319 | std::array<int, 5> x{}; |
320 | auto aref = MutableArrayRef(x); |
321 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
322 | EXPECT_EQ(aref.data(), x.data()); |
323 | EXPECT_EQ(aref.size(), x.size()); |
324 | } |
325 | |
326 | // MutableArrayRef |
327 | { |
328 | MutableArrayRef<int> x{}; |
329 | auto aref = MutableArrayRef(x); |
330 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
331 | EXPECT_EQ(aref.data(), x.data()); |
332 | EXPECT_EQ(aref.size(), x.size()); |
333 | |
334 | const MutableArrayRef<int> y{}; |
335 | auto aref2 = MutableArrayRef(y); |
336 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>); |
337 | EXPECT_EQ(aref2.data(), y.data()); |
338 | EXPECT_EQ(aref2.size(), y.size()); |
339 | } |
340 | |
341 | // C-style array |
342 | { |
343 | int x[] = {0, 1, 2, 3}; |
344 | auto aref = MutableArrayRef(x); |
345 | static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>); |
346 | EXPECT_EQ(aref.data(), &x[0]); |
347 | EXPECT_EQ(aref.size(), 4u); |
348 | } |
349 | } |
350 | |
351 | } // end anonymous namespace |
352 | |