xref: /llvm-project/llvm/unittests/ADT/IListIteratorBitsTest.cpp (revision 0863bd83e573f5e3e35c5c6b5750ac74f2295f48)
1 //==- unittests/ADT/IListIteratorBitsTest.cpp - ilist_iterator_w_bits 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/simple_ilist.h"
10 #include "gtest/gtest.h"
11 
12 // Test that ilist_iterator_w_bits can be used to store extra information about
13 // what we're iterating over, that it's only enabled when given the relevant
14 // option, and it can be fed into various iteration utilities.
15 
16 using namespace llvm;
17 
18 namespace {
19 
20 class dummy;
21 
22 struct Node : ilist_node<Node, ilist_iterator_bits<true>> {
23   friend class dummy;
24 };
25 
26 struct PlainNode : ilist_node<PlainNode> {
27   friend class dummy;
28 };
29 
30 class Parent {};
31 struct ParentNode
32     : ilist_node<ParentNode, ilist_iterator_bits<true>, ilist_parent<Parent>> {
33 };
34 
TEST(IListIteratorBitsTest,DefaultConstructor)35 TEST(IListIteratorBitsTest, DefaultConstructor) {
36   simple_ilist<Node, ilist_iterator_bits<true>>::iterator I;
37   simple_ilist<Node, ilist_iterator_bits<true>>::reverse_iterator RI;
38   simple_ilist<Node, ilist_iterator_bits<true>>::const_iterator CI;
39   simple_ilist<Node, ilist_iterator_bits<true>>::const_reverse_iterator CRI;
40   EXPECT_EQ(nullptr, I.getNodePtr());
41   EXPECT_EQ(nullptr, CI.getNodePtr());
42   EXPECT_EQ(nullptr, RI.getNodePtr());
43   EXPECT_EQ(nullptr, CRI.getNodePtr());
44   EXPECT_EQ(I, I);
45   EXPECT_EQ(I, CI);
46   EXPECT_EQ(CI, I);
47   EXPECT_EQ(CI, CI);
48   EXPECT_EQ(RI, RI);
49   EXPECT_EQ(RI, CRI);
50   EXPECT_EQ(CRI, RI);
51   EXPECT_EQ(CRI, CRI);
52   EXPECT_EQ(I, RI.getReverse());
53   EXPECT_EQ(RI, I.getReverse());
54 }
55 
TEST(IListIteratorBitsTest,ConsAndAssignment)56 TEST(IListIteratorBitsTest, ConsAndAssignment) {
57   simple_ilist<Node, ilist_iterator_bits<true>> L;
58   Node A;
59   L.insert(L.end(), A);
60 
61   simple_ilist<Node, ilist_iterator_bits<true>>::iterator I, I2;
62 
63   // Check that HeadInclusiveBit and TailInclusiveBit are preserved on
64   // assignment and copy construction, but not on other operations.
65   I = L.begin();
66   EXPECT_FALSE(I.getHeadBit());
67   EXPECT_FALSE(I.getTailBit());
68   I.setHeadBit(true);
69   I.setTailBit(true);
70   EXPECT_TRUE(I.getHeadBit());
71   EXPECT_TRUE(I.getTailBit());
72 
73   ++I;
74 
75   EXPECT_FALSE(I.getHeadBit());
76   EXPECT_FALSE(I.getTailBit());
77 
78   I = L.begin();
79   I.setHeadBit(true);
80   I.setTailBit(true);
81   I2 = I;
82   EXPECT_TRUE(I2.getHeadBit());
83   EXPECT_TRUE(I2.getTailBit());
84 
85   I = L.begin();
86   I.setHeadBit(true);
87   I.setTailBit(true);
88   simple_ilist<Node, ilist_iterator_bits<true>>::iterator I3(I);
89   EXPECT_TRUE(I3.getHeadBit());
90   EXPECT_TRUE(I3.getTailBit());
91 }
92 
93 class dummy {
94   // Test that we get an ilist_iterator_w_bits out of the node given that the
95   // options are enabled.
96   using node_options = typename ilist_detail::compute_node_options<
97       Node, ilist_iterator_bits<true>>::type;
98   static_assert(std::is_same<Node::self_iterator,
99                              llvm::ilist_iterator_w_bits<node_options, false,
100                                                          false>>::value);
101 
102   // Now test that a plain node, without the option, gets a plain
103   // ilist_iterator.
104   using plain_node_options =
105       typename ilist_detail::compute_node_options<PlainNode>::type;
106   static_assert(std::is_same<
107                 PlainNode::self_iterator,
108                 llvm::ilist_iterator<plain_node_options, false, false>>::value);
109 };
110 
TEST(IListIteratorBitsTest,RangeIteration)111 TEST(IListIteratorBitsTest, RangeIteration) {
112   // Check that we can feed ilist_iterator_w_bits into make_range and similar.
113   // Plus, we should be able to convert it to a reverse iterator and use that.
114   simple_ilist<Node, ilist_iterator_bits<true>> L;
115   Node A;
116   L.insert(L.end(), A);
117 
118   for (Node &N : make_range(L.begin(), L.end()))
119     (void)N;
120 
121   simple_ilist<Node, ilist_iterator_bits<true>>::iterator It =
122       L.begin()->getIterator();
123   auto RevIt = It.getReverse();
124 
125   for (Node &N : make_range(RevIt, L.rend()))
126     (void)N;
127 }
128 
TEST(IListIteratorBitsTest,GetParent)129 TEST(IListIteratorBitsTest, GetParent) {
130   simple_ilist<ParentNode, ilist_iterator_bits<true>, ilist_parent<Parent>> L;
131   Parent P;
132   ParentNode A;
133 
134   // Parents are not set automatically.
135   A.setParent(&P);
136   L.insert(L.end(), A);
137   L.end().getNodePtr()->setParent(&P);
138 
139   // Check we can get the node parent from all iterators, including for the
140   // sentinel.
141   EXPECT_EQ(&P, L.begin().getNodeParent());
142   EXPECT_EQ(&P, L.end().getNodeParent());
143   EXPECT_EQ(&P, L.rbegin().getNodeParent());
144   EXPECT_EQ(&P, L.rend().getNodeParent());
145 }
146 
147 } // end namespace
148