llvm.org GIT mirror llvm / 30b148e
Add TinyPtrVector support for general pointer-like things. In particular, make TinyPtrVector<PtrIntPair<T *, 1>> work. Remove all unnecessary assumptions that the element type has a formal "null" representation. The important property to maintain is that default-constructed element type has the same internal representation as the default-constructed PointerUnion (all zero bits). Remove the incorrect recursive behavior from PointerUnion::isNull. This was never generally correct because it only recursed over the first type parameter. With variadic templates it's completely unnecessary. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@369473 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Trick 30 days ago
4 changed file(s) with 100 addition(s) and 35 deletion(s). Raw diff Collapse all Expand all
159159 void *, pointer_union_detail::bitsRequired(sizeof...(PTs)), int,
160160 pointer_union_detail::PointerUnionUIntTraits>,
161161 0, PTs...> {
162 // The first type is special in some ways, but we don't want PointerUnion to
163 // be a 'template ' because it's much more
164 // convenient to have a name for the whole pack. So split off the first type
165 // here.
162 // The first type is special because we want to directly cast a pointer to a
163 // default-initialized union to a pointer to the first type. But we don't
164 // want PointerUnion to be a 'template '
165 // because it's much more convenient to have a name for the whole pack. So
166 // split off the first type here.
166167 using First = typename pointer_union_detail::GetFirstType::type;
167168 using Base = typename PointerUnion::PointerUnionMembers;
168169
174175
175176 /// Test if the pointer held in the union is null, regardless of
176177 /// which type it is.
177 bool isNull() const {
178 // Convert from the void* to one of the pointer types, to make sure that
179 // we recursively strip off low bits if we have a nested PointerUnion.
180 return !PointerLikeTypeTraits::getFromVoidPointer(
181 this->Val.getPointer());
182 }
178 bool isNull() const { return !this->Val.getPointer(); }
183179
184180 explicit operator bool() const { return !isNull(); }
185181
218214 First *getAddrOfPtr1() {
219215 assert(is() && "Val is not the first pointer");
220216 assert(
221 get() == this->Val.getPointer() &&
217 PointerLikeTypeTraits::getAsVoidPointer(get()) ==
218 this->Val.getPointer() &&
222219 "Can't get the address because PointerLikeTypeTraits changes the ptr");
223220 return const_cast(
224221 reinterpret_cast(this->Val.getAddrOfPointer()));
3030 public:
3131 using VecTy = SmallVector;
3232 using value_type = typename VecTy::value_type;
33 // EltTy must be the first pointer type so that is is true for the
34 // default-constructed PtrUnion. This allows an empty TinyPtrVector to
35 // naturally vend a begin/end iterator of type EltTy* without an additional
36 // check for the empty state.
3337 using PtrUnion = PointerUnion;
3438
3539 private:
9599 if (RHS.Val.template is()) {
96100 V->clear();
97101 V->push_back(RHS.front());
98 RHS.Val = (EltTy)nullptr;
102 RHS.Val = EltTy();
99103 return *this;
100104 }
101105 delete V;
102106 }
103107
104108 Val = RHS.Val;
105 RHS.Val = (EltTy)nullptr;
109 RHS.Val = EltTy();
106110 return *this;
107111 }
108112
212216
213217 EltTy operator[](unsigned i) const {
214218 assert(!Val.isNull() && "can't index into an empty vector");
215 if (EltTy V = Val.template dyn_cast()) {
219 if (Val.template is()) {
216220 assert(i == 0 && "tinyvector index out of range");
217 return V;
221 return Val.template get();
218222 }
219223
220224 assert(i < Val.template get()->size() &&
224228
225229 EltTy front() const {
226230 assert(!empty() && "vector empty");
227 if (EltTy V = Val.template dyn_cast())
228 return V;
231 if (Val.template is())
232 return Val.template get();
229233 return Val.template get()->front();
230234 }
231235
232236 EltTy back() const {
233237 assert(!empty() && "vector empty");
234 if (EltTy V = Val.template dyn_cast())
235 return V;
238 if (Val.template is())
239 return Val.template get();
236240 return Val.template get()->back();
237241 }
238242
239243 void push_back(EltTy NewVal) {
240 assert(NewVal && "Can't add a null value");
241
242244 // If we have nothing, add something.
243245 if (Val.isNull()) {
244246 Val = NewVal;
247 assert(!Val.isNull() && "Can't add a null value");
245248 return;
246249 }
247250
248251 // If we have a single value, convert to a vector.
249 if (EltTy V = Val.template dyn_cast()) {
252 if (Val.template is()) {
253 EltTy V = Val.template get();
250254 Val = new VecTy();
251255 Val.template get()->push_back(V);
252256 }
266270 void clear() {
267271 // If we have a single value, convert to empty.
268272 if (Val.template is()) {
269 Val = (EltTy)nullptr;
273 Val = EltTy();
270274 } else if (VecTy *Vec = Val.template dyn_cast()) {
271275 // If we have a vector form, just clear it.
272276 Vec->clear();
281285 // If we have a single value, convert to empty.
282286 if (Val.template is()) {
283287 if (I == begin())
284 Val = (EltTy)nullptr;
288 Val = EltTy();
285289 } else if (VecTy *Vec = Val.template dyn_cast()) {
286290 // multiple items in a vector; just do the erase, there is no
287291 // benefit to collapsing back to a pointer
297301
298302 if (Val.template is()) {
299303 if (S == begin() && S != E)
300 Val = (EltTy)nullptr;
304 Val = EltTy();
301305 } else if (VecTy *Vec = Val.template dyn_cast()) {
302306 return Vec->erase(S, E);
303307 }
312316 return std::prev(end());
313317 }
314318 assert(!Val.isNull() && "Null value with non-end insert iterator.");
315 if (EltTy V = Val.template dyn_cast()) {
319 if (Val.template is()) {
320 EltTy V = Val.template get();
316321 assert(I == begin());
317322 Val = Elt;
318323 push_back(V);
338343 }
339344
340345 Val = new VecTy();
341 } else if (EltTy V = Val.template dyn_cast()) {
346 } else if (Val.template is()) {
347 EltTy V = Val.template get();
342348 Val = new VecTy();
343349 Val.template get()->push_back(V);
344350 }
1212 namespace {
1313
1414 typedef PointerUnion PU;
15 typedef PointerUnion3 PU3;
16 typedef PointerUnion4 PU4;
1517
1618 struct PointerUnionTest : public testing::Test {
1719 float f;
1820 int i;
21 double d;
22 long long l;
1923
2024 PU a, b, c, n;
25 PU3 i3, f3, l3;
26 PU4 i4, f4, l4, d4;
27 PU4 i4null, f4null, l4null, d4null;
2128
22 PointerUnionTest() : f(3.14f), i(42), a(&f), b(&i), c(&i), n() {}
29 PointerUnionTest()
30 : f(3.14f), i(42), d(3.14), l(42), a(&f), b(&i), c(&i), n(), i3(&i),
31 f3(&f), l3(&l), i4(&i), f4(&f), l4(&l), d4(&d), i4null((int *)nullptr),
32 f4null((float *)nullptr), l4null((long long *)nullptr),
33 d4null((double *)nullptr) {}
2334 };
2435
2536 TEST_F(PointerUnionTest, Comparison) {
3142 EXPECT_FALSE(b != c);
3243 EXPECT_TRUE(b != n);
3344 EXPECT_FALSE(b == n);
45 EXPECT_TRUE(i3 == i3);
46 EXPECT_FALSE(i3 != i3);
47 EXPECT_TRUE(i3 != f3);
48 EXPECT_TRUE(f3 != l3);
49 EXPECT_TRUE(i4 == i4);
50 EXPECT_FALSE(i4 != i4);
51 EXPECT_TRUE(i4 != f4);
52 EXPECT_TRUE(i4 != l4);
53 EXPECT_TRUE(f4 != l4);
54 EXPECT_TRUE(l4 != d4);
55 EXPECT_TRUE(i4null != f4null);
56 EXPECT_TRUE(i4null != l4null);
57 EXPECT_TRUE(i4null != d4null);
3458 }
3559
3660 TEST_F(PointerUnionTest, Null) {
5074 b = nullptr;
5175 EXPECT_EQ(n, b);
5276 EXPECT_NE(b, c);
77 EXPECT_FALSE(i3.isNull());
78 EXPECT_FALSE(f3.isNull());
79 EXPECT_FALSE(l3.isNull());
80 EXPECT_FALSE(i4.isNull());
81 EXPECT_FALSE(f4.isNull());
82 EXPECT_FALSE(l4.isNull());
83 EXPECT_FALSE(d4.isNull());
84 EXPECT_TRUE(i4null.isNull());
85 EXPECT_TRUE(f4null.isNull());
86 EXPECT_TRUE(l4null.isNull());
87 EXPECT_TRUE(d4null.isNull());
5388 }
5489
5590 TEST_F(PointerUnionTest, Is) {
5994 EXPECT_FALSE(b.is());
6095 EXPECT_TRUE(n.is());
6196 EXPECT_FALSE(n.is());
97 EXPECT_TRUE(i3.is());
98 EXPECT_TRUE(f3.is());
99 EXPECT_TRUE(l3.is());
100 EXPECT_TRUE(i4.is());
101 EXPECT_TRUE(f4.is());
102 EXPECT_TRUE(l4.is());
103 EXPECT_TRUE(d4.is());
104 EXPECT_TRUE(i4null.is());
105 EXPECT_TRUE(f4null.is());
106 EXPECT_TRUE(l4null.is());
107 EXPECT_TRUE(d4null.is());
62108 }
63109
64110 TEST_F(PointerUnionTest, Get) {
104150 EXPECT_TRUE(a != PU8(&a0));
105151 }
106152
153 TEST_F(PointerUnionTest, GetAddrOfPtr1) {
154 EXPECT_TRUE((void *)b.getAddrOfPtr1() == (void *)&b);
155 EXPECT_TRUE((void *)n.getAddrOfPtr1() == (void *)&n);
156 }
157
107158 } // end anonymous namespace
2121 using namespace llvm;
2222
2323 namespace {
24 template struct RemovePointer : std::remove_pointer {};
25
26 template
27 typename PtrTraits, typename Info>
28 struct RemovePointer<
29 PointerIntPair> {
30 typedef typename RemovePointer::type type;
31 };
2432
2533 template
2634 class TinyPtrVectorTest : public testing::Test {
2735 protected:
2836 typedef typename VectorT::value_type PtrT;
29 typedef typename std::remove_pointer::type ValueT;
37 typedef typename RemovePointer::type ValueT;
38 using PtrTraits = PointerLikeTypeTraits;
3039
3140 VectorT V;
3241 VectorT V2;
3645
3746 TinyPtrVectorTest() {
3847 for (size_t i = 0, e = array_lengthof(TestValues); i != e; ++i)
39 TestPtrs.push_back(&TestValues[i]);
48 TestPtrs.push_back(PtrT(&TestValues[i]));
4049
4150 std::shuffle(TestPtrs.begin(), TestPtrs.end(), std::mt19937{});
4251 }
52
53 PtrT makePtr(ValueT *V) { return PtrT(V); }
4354
4455 ArrayRef testArray(size_t N) {
4556 return makeArrayRef(&TestPtrs[0], N);
6879 }
6980 };
7081
71 typedef ::testing::Types,
72 TinyPtrVector
73 > TinyPtrVectorTestTypes;
82 typedef ::testing::Types, TinyPtrVector,
83 TinyPtrVector>>
84 TinyPtrVectorTestTypes;
7485 TYPED_TEST_CASE(TinyPtrVectorTest, TinyPtrVectorTestTypes);
7586
7687 TYPED_TEST(TinyPtrVectorTest, EmptyTest) {
94105 this->expectValues(this->V, this->testArray(4));
95106 this->V.pop_back();
96107 this->expectValues(this->V, this->testArray(3));
97 this->TestPtrs[3] = &this->TestValues[42];
98 this->TestPtrs[4] = &this->TestValues[43];
108 this->TestPtrs[3] = this->makePtr(&this->TestValues[42]);
109 this->TestPtrs[4] = this->makePtr(&this->TestValues[43]);
99110 this->V.push_back(this->TestPtrs[3]);
100111 this->expectValues(this->V, this->testArray(4));
101112 this->V.push_back(this->TestPtrs[4]);