[docs] Fix build-docs.sh
[llvm-project.git] / llvm / unittests / ADT / IteratorTest.cpp
blob7269bfc4b6fb0af8d45fe713f72c8e130a560715
1 //===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/ilist.h"
10 #include "llvm/ADT/iterator.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/SmallVector.h"
14 #include "gtest/gtest.h"
16 using namespace llvm;
18 namespace {
20 template <int> struct Shadow;
22 struct WeirdIter
23 : llvm::iterator_facade_base<WeirdIter, std::input_iterator_tag, Shadow<0>,
24 Shadow<1>, Shadow<2>, Shadow<3>> {};
26 struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
28 // Test that iterator_adaptor_base forwards typedefs, if value_type is
29 // unchanged.
30 static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
31 "");
32 static_assert(
33 std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
34 static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
35 "");
36 static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
37 "");
39 // Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
40 // the underlying iterator.
42 using RandomAccessIter = SmallVectorImpl<int*>::iterator;
43 using BidiIter = ilist<int*>::iterator;
45 template<class T>
46 using pointee_iterator_defaulted = pointee_iterator<T>;
47 template<class T>
48 using pointer_iterator_defaulted = pointer_iterator<T>;
50 // Ensures that an iterator and its adaptation have the same iterator_category.
51 template<template<typename> class A, typename It>
52 using IsAdaptedIterCategorySame =
53 std::is_same<typename std::iterator_traits<It>::iterator_category,
54 typename std::iterator_traits<A<It>>::iterator_category>;
56 // Check that dereferencing works correctly adapting pointers and proxies.
57 template <class T>
58 struct PointerWrapper : public iterator_adaptor_base<PointerWrapper<T>, T *> {
59 PointerWrapper(T *I) : PointerWrapper::iterator_adaptor_base(I) {}
61 struct IntProxy {
62 int &I;
63 IntProxy(int &I) : I(I) {}
64 void operator=(int NewValue) { I = NewValue; }
66 struct ConstIntProxy {
67 const int &I;
68 ConstIntProxy(const int &I) : I(I) {}
70 template <class T, class ProxyT>
71 struct PointerProxyWrapper
72 : public iterator_adaptor_base<PointerProxyWrapper<T, ProxyT>, T *,
73 std::random_access_iterator_tag, T,
74 ptrdiff_t, T *, ProxyT> {
75 PointerProxyWrapper(T *I) : PointerProxyWrapper::iterator_adaptor_base(I) {}
77 using IntIterator = PointerWrapper<int>;
78 using ConstIntIterator = PointerWrapper<const int>;
79 using IntProxyIterator = PointerProxyWrapper<int, IntProxy>;
80 using ConstIntProxyIterator = PointerProxyWrapper<const int, ConstIntProxy>;
82 // There should only be a single (const-qualified) operator*, operator->, and
83 // operator[]. This test confirms that there isn't a non-const overload. Rather
84 // than adding those, users should double-check that T, PointerT, and ReferenceT
85 // have the right constness, and/or make fields mutable.
86 static_assert(&IntIterator::operator* == &IntIterator::operator*, "");
87 static_assert(&IntIterator::operator-> == &IntIterator::operator->, "");
88 static_assert(&IntIterator::operator[] == &IntIterator::operator[], "");
90 template <class T,
91 std::enable_if_t<std::is_assignable<T, int>::value, bool> = false>
92 constexpr bool canAssignFromInt(T &&) {
93 return true;
95 template <class T,
96 std::enable_if_t<!std::is_assignable<T, int>::value, bool> = false>
97 constexpr bool canAssignFromInt(T &&) {
98 return false;
101 TEST(IteratorAdaptorTest, Dereference) {
102 int Number = 1;
104 // Construct some iterators and check whether they can be assigned to.
105 IntIterator I(&Number);
106 const IntIterator IC(&Number);
107 ConstIntIterator CI(&Number);
108 const ConstIntIterator CIC(&Number);
109 EXPECT_EQ(true, canAssignFromInt(*I)); // int *
110 EXPECT_EQ(true, canAssignFromInt(*IC)); // int *const
111 EXPECT_EQ(false, canAssignFromInt(*CI)); // const int *
112 EXPECT_EQ(false, canAssignFromInt(*CIC)); // const int *const
114 // Prove that dereference and assignment work.
115 EXPECT_EQ(1, *I);
116 EXPECT_EQ(1, *IC);
117 EXPECT_EQ(1, *CI);
118 EXPECT_EQ(1, *CIC);
119 *I = 2;
120 EXPECT_EQ(2, Number);
121 *IC = 3;
122 EXPECT_EQ(3, Number);
124 // Construct some proxy iterators and check whether they can be assigned to.
125 IntProxyIterator P(&Number);
126 const IntProxyIterator PC(&Number);
127 ConstIntProxyIterator CP(&Number);
128 const ConstIntProxyIterator CPC(&Number);
129 EXPECT_EQ(true, canAssignFromInt(*P)); // int *
130 EXPECT_EQ(true, canAssignFromInt(*PC)); // int *const
131 EXPECT_EQ(false, canAssignFromInt(*CP)); // const int *
132 EXPECT_EQ(false, canAssignFromInt(*CPC)); // const int *const
134 // Prove that dereference and assignment work.
135 EXPECT_EQ(3, (*P).I);
136 EXPECT_EQ(3, (*PC).I);
137 EXPECT_EQ(3, (*CP).I);
138 EXPECT_EQ(3, (*CPC).I);
139 *P = 4;
140 EXPECT_EQ(4, Number);
141 *PC = 5;
142 EXPECT_EQ(5, Number);
145 // pointeE_iterator
146 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
147 RandomAccessIter>::value, "");
148 static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
149 BidiIter>::value, "");
150 // pointeR_iterator
151 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
152 RandomAccessIter>::value, "");
153 static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
154 BidiIter>::value, "");
156 TEST(PointeeIteratorTest, Basic) {
157 int arr[4] = {1, 2, 3, 4};
158 SmallVector<int *, 4> V;
159 V.push_back(&arr[0]);
160 V.push_back(&arr[1]);
161 V.push_back(&arr[2]);
162 V.push_back(&arr[3]);
164 typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
165 test_iterator;
167 test_iterator Begin, End;
168 Begin = V.begin();
169 End = test_iterator(V.end());
171 test_iterator I = Begin;
172 for (int i = 0; i < 4; ++i) {
173 EXPECT_EQ(*V[i], *I);
175 EXPECT_EQ(I, Begin + i);
176 EXPECT_EQ(I, std::next(Begin, i));
177 test_iterator J = Begin;
178 J += i;
179 EXPECT_EQ(I, J);
180 EXPECT_EQ(*V[i], Begin[i]);
182 EXPECT_NE(I, End);
183 EXPECT_GT(End, I);
184 EXPECT_LT(I, End);
185 EXPECT_GE(I, Begin);
186 EXPECT_LE(Begin, I);
188 EXPECT_EQ(i, I - Begin);
189 EXPECT_EQ(i, std::distance(Begin, I));
190 EXPECT_EQ(Begin, I - i);
192 test_iterator K = I++;
193 EXPECT_EQ(K, std::prev(I));
195 EXPECT_EQ(End, I);
198 TEST(PointeeIteratorTest, SmartPointer) {
199 SmallVector<std::unique_ptr<int>, 4> V;
200 V.push_back(std::make_unique<int>(1));
201 V.push_back(std::make_unique<int>(2));
202 V.push_back(std::make_unique<int>(3));
203 V.push_back(std::make_unique<int>(4));
205 typedef pointee_iterator<
206 SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
207 test_iterator;
209 test_iterator Begin, End;
210 Begin = V.begin();
211 End = test_iterator(V.end());
213 test_iterator I = Begin;
214 for (int i = 0; i < 4; ++i) {
215 EXPECT_EQ(*V[i], *I);
217 EXPECT_EQ(I, Begin + i);
218 EXPECT_EQ(I, std::next(Begin, i));
219 test_iterator J = Begin;
220 J += i;
221 EXPECT_EQ(I, J);
222 EXPECT_EQ(*V[i], Begin[i]);
224 EXPECT_NE(I, End);
225 EXPECT_GT(End, I);
226 EXPECT_LT(I, End);
227 EXPECT_GE(I, Begin);
228 EXPECT_LE(Begin, I);
230 EXPECT_EQ(i, I - Begin);
231 EXPECT_EQ(i, std::distance(Begin, I));
232 EXPECT_EQ(Begin, I - i);
234 test_iterator K = I++;
235 EXPECT_EQ(K, std::prev(I));
237 EXPECT_EQ(End, I);
240 TEST(PointeeIteratorTest, Range) {
241 int A[] = {1, 2, 3, 4};
242 SmallVector<int *, 4> V{&A[0], &A[1], &A[2], &A[3]};
244 int I = 0;
245 for (int II : make_pointee_range(V))
246 EXPECT_EQ(A[I++], II);
249 TEST(PointeeIteratorTest, PointeeType) {
250 struct S {
251 int X;
252 bool operator==(const S &RHS) const { return X == RHS.X; };
254 S A[] = {S{0}, S{1}};
255 SmallVector<S *, 2> V{&A[0], &A[1]};
257 pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
258 for (int j = 0; j < 2; ++j, ++I) {
259 EXPECT_EQ(*V[j], *I);
263 TEST(FilterIteratorTest, Lambda) {
264 auto IsOdd = [](int N) { return N % 2 == 1; };
265 int A[] = {0, 1, 2, 3, 4, 5, 6};
266 auto Range = make_filter_range(A, IsOdd);
267 SmallVector<int, 3> Actual(Range.begin(), Range.end());
268 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
271 TEST(FilterIteratorTest, Enumerate) {
272 auto IsOdd = [](auto N) { return N.value() % 2 == 1; };
273 int A[] = {0, 1, 2, 3, 4, 5, 6};
274 auto Enumerate = llvm::enumerate(A);
275 SmallVector<int> Actual;
276 for (auto IndexedValue : make_filter_range(Enumerate, IsOdd))
277 Actual.push_back(IndexedValue.value());
278 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
281 TEST(FilterIteratorTest, CallableObject) {
282 int Counter = 0;
283 struct Callable {
284 int &Counter;
286 Callable(int &Counter) : Counter(Counter) {}
288 bool operator()(int N) {
289 Counter++;
290 return N % 2 == 1;
293 Callable IsOdd(Counter);
294 int A[] = {0, 1, 2, 3, 4, 5, 6};
295 auto Range = make_filter_range(A, IsOdd);
296 EXPECT_EQ(2, Counter);
297 SmallVector<int, 3> Actual(Range.begin(), Range.end());
298 EXPECT_GE(Counter, 7);
299 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
302 TEST(FilterIteratorTest, FunctionPointer) {
303 bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
304 int A[] = {0, 1, 2, 3, 4, 5, 6};
305 auto Range = make_filter_range(A, IsOdd);
306 SmallVector<int, 3> Actual(Range.begin(), Range.end());
307 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
310 TEST(FilterIteratorTest, Composition) {
311 auto IsOdd = [](int N) { return N % 2 == 1; };
312 std::unique_ptr<int> A[] = {std::make_unique<int>(0), std::make_unique<int>(1),
313 std::make_unique<int>(2), std::make_unique<int>(3),
314 std::make_unique<int>(4), std::make_unique<int>(5),
315 std::make_unique<int>(6)};
316 using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
317 auto Range = make_filter_range(
318 make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
319 IsOdd);
320 SmallVector<int, 3> Actual(Range.begin(), Range.end());
321 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
324 TEST(FilterIteratorTest, InputIterator) {
325 struct InputIterator
326 : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
327 InputIterator(int *It) : InputIterator::iterator_adaptor_base(It) {}
330 auto IsOdd = [](int N) { return N % 2 == 1; };
331 int A[] = {0, 1, 2, 3, 4, 5, 6};
332 auto Range = make_filter_range(
333 make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
334 IsOdd);
335 SmallVector<int, 3> Actual(Range.begin(), Range.end());
336 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
339 TEST(FilterIteratorTest, ReverseFilterRange) {
340 auto IsOdd = [](int N) { return N % 2 == 1; };
341 int A[] = {0, 1, 2, 3, 4, 5, 6};
343 // Check basic reversal.
344 auto Range = reverse(make_filter_range(A, IsOdd));
345 SmallVector<int, 3> Actual(Range.begin(), Range.end());
346 EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
348 // Check that the reverse of the reverse is the original.
349 auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
350 SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
351 EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
353 // Check empty ranges.
354 auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
355 SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
356 EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
358 // Check that we don't skip the first element, provided it isn't filtered
359 // away.
360 auto IsEven = [](int N) { return N % 2 == 0; };
361 auto Range4 = reverse(make_filter_range(A, IsEven));
362 SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
363 EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
366 TEST(PointerIterator, Basic) {
367 int A[] = {1, 2, 3, 4};
368 pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
369 EXPECT_EQ(A, *Begin);
370 ++Begin;
371 EXPECT_EQ(A + 1, *Begin);
372 ++Begin;
373 EXPECT_EQ(A + 2, *Begin);
374 ++Begin;
375 EXPECT_EQ(A + 3, *Begin);
376 ++Begin;
377 EXPECT_EQ(Begin, End);
380 TEST(PointerIterator, Const) {
381 int A[] = {1, 2, 3, 4};
382 const pointer_iterator<int *> Begin(std::begin(A));
383 EXPECT_EQ(A, *Begin);
384 EXPECT_EQ(A + 1, std::next(*Begin, 1));
385 EXPECT_EQ(A + 2, std::next(*Begin, 2));
386 EXPECT_EQ(A + 3, std::next(*Begin, 3));
387 EXPECT_EQ(A + 4, std::next(*Begin, 4));
390 TEST(PointerIterator, Range) {
391 int A[] = {1, 2, 3, 4};
392 int I = 0;
393 for (int *P : make_pointer_range(A))
394 EXPECT_EQ(A + I++, P);
397 TEST(ZipIteratorTest, Basic) {
398 using namespace std;
399 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
400 SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
401 const char message[] = "yynyyy\0";
403 for (auto tup : zip(pi, odd, message)) {
404 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
405 EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
408 // note the rvalue
409 for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
410 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
414 TEST(ZipIteratorTest, ZipFirstBasic) {
415 using namespace std;
416 const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
417 unsigned iters = 0;
419 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
420 EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
421 iters += 1;
424 EXPECT_EQ(iters, 4u);
427 TEST(ZipIteratorTest, ZipLongestBasic) {
428 using namespace std;
429 const vector<unsigned> pi{3, 1, 4, 1, 5, 9};
430 const vector<StringRef> e{"2", "7", "1", "8"};
433 // Check left range longer than right.
434 const vector<tuple<Optional<unsigned>, Optional<StringRef>>> expected{
435 make_tuple(3, StringRef("2")), make_tuple(1, StringRef("7")),
436 make_tuple(4, StringRef("1")), make_tuple(1, StringRef("8")),
437 make_tuple(5, None), make_tuple(9, None)};
438 size_t iters = 0;
439 for (auto tup : zip_longest(pi, e)) {
440 EXPECT_EQ(tup, expected[iters]);
441 iters += 1;
443 EXPECT_EQ(iters, expected.size());
447 // Check right range longer than left.
448 const vector<tuple<Optional<StringRef>, Optional<unsigned>>> expected{
449 make_tuple(StringRef("2"), 3), make_tuple(StringRef("7"), 1),
450 make_tuple(StringRef("1"), 4), make_tuple(StringRef("8"), 1),
451 make_tuple(None, 5), make_tuple(None, 9)};
452 size_t iters = 0;
453 for (auto tup : zip_longest(e, pi)) {
454 EXPECT_EQ(tup, expected[iters]);
455 iters += 1;
457 EXPECT_EQ(iters, expected.size());
461 TEST(ZipIteratorTest, Mutability) {
462 using namespace std;
463 const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
464 char message[] = "hello zip\0";
466 for (auto tup : zip(pi, message, message)) {
467 EXPECT_EQ(get<1>(tup), get<2>(tup));
468 get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
471 // note the rvalue
472 for (auto tup : zip(message, "yynyyyzip\0")) {
473 EXPECT_EQ(get<0>(tup), get<1>(tup));
477 TEST(ZipIteratorTest, ZipFirstMutability) {
478 using namespace std;
479 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
480 unsigned iters = 0;
482 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
483 get<1>(tup) = get<0>(tup);
484 iters += 1;
487 EXPECT_EQ(iters, 4u);
489 for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
490 EXPECT_EQ(get<0>(tup), get<1>(tup));
494 TEST(ZipIteratorTest, Filter) {
495 using namespace std;
496 vector<unsigned> pi{3, 1, 4, 1, 5, 9};
498 unsigned iters = 0;
499 // pi is length 6, but the zip RHS is length 7.
500 auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
501 for (auto tup : make_filter_range(
502 zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
503 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
504 get<0>(tup) += 1;
505 iters += 1;
508 // Should have skipped pi[2].
509 EXPECT_EQ(iters, 5u);
511 // Ensure that in-place mutation works.
512 EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
515 TEST(ZipIteratorTest, Reverse) {
516 using namespace std;
517 vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
519 auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
520 unsigned last = 6;
521 for (auto tup : reverse(zipped)) {
522 // Check that this is in reverse.
523 EXPECT_LT(get<0>(tup), last);
524 last = get<0>(tup);
525 EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
528 auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
529 last = 6;
530 for (auto tup : make_filter_range(reverse(zipped), odds)) {
531 EXPECT_LT(get<0>(tup), last);
532 last = get<0>(tup);
533 EXPECT_TRUE(get<0>(tup) & 0x01);
534 get<0>(tup) += 1;
537 // Ensure that in-place mutation works.
538 EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
541 TEST(RangeTest, Distance) {
542 std::vector<int> v1;
543 std::vector<int> v2{1, 2, 3};
545 EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
546 EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
549 } // anonymous namespace