xref: /llvm-project/llvm/unittests/ADT/DenseMapTest.cpp (revision be83a4b257c8f0dfd74a659261a544483c5df9af)
1 //===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
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/DenseMap.h"
10 #include "llvm/ADT/DenseMapInfo.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 #include <map>
14 #include <set>
15 #include <utility>
16 #include <variant>
17 
18 using namespace llvm;
19 
20 namespace {
21 
22 uint32_t getTestKey(int i, uint32_t *) { return i; }
23 uint32_t getTestValue(int i, uint32_t *) { return 42 + i; }
24 
25 uint32_t *getTestKey(int i, uint32_t **) {
26   static uint32_t dummy_arr1[8192];
27   assert(i < 8192 && "Only support 8192 dummy keys.");
28   return &dummy_arr1[i];
29 }
30 uint32_t *getTestValue(int i, uint32_t **) {
31   static uint32_t dummy_arr1[8192];
32   assert(i < 8192 && "Only support 8192 dummy keys.");
33   return &dummy_arr1[i];
34 }
35 
36 /// A test class that tries to check that construction and destruction
37 /// occur correctly.
38 class CtorTester {
39   static std::set<CtorTester *> Constructed;
40   int Value;
41 
42 public:
43   explicit CtorTester(int Value = 0) : Value(Value) {
44     EXPECT_TRUE(Constructed.insert(this).second);
45   }
46   CtorTester(uint32_t Value) : Value(Value) {
47     EXPECT_TRUE(Constructed.insert(this).second);
48   }
49   CtorTester(const CtorTester &Arg) : Value(Arg.Value) {
50     EXPECT_TRUE(Constructed.insert(this).second);
51   }
52   CtorTester &operator=(const CtorTester &) = default;
53   ~CtorTester() {
54     EXPECT_EQ(1u, Constructed.erase(this));
55   }
56   operator uint32_t() const { return Value; }
57 
58   int getValue() const { return Value; }
59   bool operator==(const CtorTester &RHS) const { return Value == RHS.Value; }
60 };
61 
62 std::set<CtorTester *> CtorTester::Constructed;
63 
64 struct CtorTesterMapInfo {
65   static inline CtorTester getEmptyKey() { return CtorTester(-1); }
66   static inline CtorTester getTombstoneKey() { return CtorTester(-2); }
67   static unsigned getHashValue(const CtorTester &Val) {
68     return Val.getValue() * 37u;
69   }
70   static bool isEqual(const CtorTester &LHS, const CtorTester &RHS) {
71     return LHS == RHS;
72   }
73 };
74 
75 CtorTester getTestKey(int i, CtorTester *) { return CtorTester(i); }
76 CtorTester getTestValue(int i, CtorTester *) { return CtorTester(42 + i); }
77 
78 // Test fixture, with helper functions implemented by forwarding to global
79 // function overloads selected by component types of the type parameter. This
80 // allows all of the map implementations to be tested with shared
81 // implementations of helper routines.
82 template <typename T>
83 class DenseMapTest : public ::testing::Test {
84 protected:
85   T Map;
86 
87   static typename T::key_type *const dummy_key_ptr;
88   static typename T::mapped_type *const dummy_value_ptr;
89 
90   typename T::key_type getKey(int i = 0) {
91     return getTestKey(i, dummy_key_ptr);
92   }
93   typename T::mapped_type getValue(int i = 0) {
94     return getTestValue(i, dummy_value_ptr);
95   }
96 };
97 
98 template <typename T>
99 typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = nullptr;
100 template <typename T>
101 typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = nullptr;
102 
103 // Register these types for testing.
104 typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
105                          DenseMap<uint32_t *, uint32_t *>,
106                          DenseMap<CtorTester, CtorTester, CtorTesterMapInfo>,
107                          SmallDenseMap<uint32_t, uint32_t>,
108                          SmallDenseMap<uint32_t *, uint32_t *>,
109                          SmallDenseMap<CtorTester, CtorTester, 4,
110                                        CtorTesterMapInfo>
111                          > DenseMapTestTypes;
112 TYPED_TEST_SUITE(DenseMapTest, DenseMapTestTypes, );
113 
114 // Empty map tests
115 TYPED_TEST(DenseMapTest, EmptyIntMapTest) {
116   // Size tests
117   EXPECT_EQ(0u, this->Map.size());
118   EXPECT_TRUE(this->Map.empty());
119 
120   // Iterator tests
121   EXPECT_TRUE(this->Map.begin() == this->Map.end());
122 
123   // Lookup tests
124   EXPECT_FALSE(this->Map.count(this->getKey()));
125   EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end());
126   EXPECT_EQ(typename TypeParam::mapped_type(),
127             this->Map.lookup(this->getKey()));
128 }
129 
130 // Constant map tests
131 TYPED_TEST(DenseMapTest, ConstEmptyMapTest) {
132   const TypeParam &ConstMap = this->Map;
133   EXPECT_EQ(0u, ConstMap.size());
134   EXPECT_TRUE(ConstMap.empty());
135   EXPECT_TRUE(ConstMap.begin() == ConstMap.end());
136 }
137 
138 // A map with a single entry
139 TYPED_TEST(DenseMapTest, SingleEntryMapTest) {
140   this->Map[this->getKey()] = this->getValue();
141 
142   // Size tests
143   EXPECT_EQ(1u, this->Map.size());
144   EXPECT_FALSE(this->Map.begin() == this->Map.end());
145   EXPECT_FALSE(this->Map.empty());
146 
147   // Iterator tests
148   typename TypeParam::iterator it = this->Map.begin();
149   EXPECT_EQ(this->getKey(), it->first);
150   EXPECT_EQ(this->getValue(), it->second);
151   ++it;
152   EXPECT_TRUE(it == this->Map.end());
153 
154   // Lookup tests
155   EXPECT_TRUE(this->Map.count(this->getKey()));
156   EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin());
157   EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey()));
158   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
159 }
160 
161 TYPED_TEST(DenseMapTest, AtTest) {
162   this->Map[this->getKey(0)] = this->getValue(0);
163   this->Map[this->getKey(1)] = this->getValue(1);
164   this->Map[this->getKey(2)] = this->getValue(2);
165   EXPECT_EQ(this->getValue(0), this->Map.at(this->getKey(0)));
166   EXPECT_EQ(this->getValue(1), this->Map.at(this->getKey(1)));
167   EXPECT_EQ(this->getValue(2), this->Map.at(this->getKey(2)));
168 }
169 
170 // Test clear() method
171 TYPED_TEST(DenseMapTest, ClearTest) {
172   this->Map[this->getKey()] = this->getValue();
173   this->Map.clear();
174 
175   EXPECT_EQ(0u, this->Map.size());
176   EXPECT_TRUE(this->Map.empty());
177   EXPECT_TRUE(this->Map.begin() == this->Map.end());
178 }
179 
180 // Test erase(iterator) method
181 TYPED_TEST(DenseMapTest, EraseTest) {
182   this->Map[this->getKey()] = this->getValue();
183   this->Map.erase(this->Map.begin());
184 
185   EXPECT_EQ(0u, this->Map.size());
186   EXPECT_TRUE(this->Map.empty());
187   EXPECT_TRUE(this->Map.begin() == this->Map.end());
188 }
189 
190 // Test erase(value) method
191 TYPED_TEST(DenseMapTest, EraseTest2) {
192   this->Map[this->getKey()] = this->getValue();
193   this->Map.erase(this->getKey());
194 
195   EXPECT_EQ(0u, this->Map.size());
196   EXPECT_TRUE(this->Map.empty());
197   EXPECT_TRUE(this->Map.begin() == this->Map.end());
198 }
199 
200 // Test insert() method
201 TYPED_TEST(DenseMapTest, InsertTest) {
202   this->Map.insert(std::make_pair(this->getKey(), this->getValue()));
203   EXPECT_EQ(1u, this->Map.size());
204   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
205 }
206 
207 // Test copy constructor method
208 TYPED_TEST(DenseMapTest, CopyConstructorTest) {
209   this->Map[this->getKey()] = this->getValue();
210   TypeParam copyMap(this->Map);
211 
212   EXPECT_EQ(1u, copyMap.size());
213   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
214 }
215 
216 // Test copy constructor method where SmallDenseMap isn't small.
217 TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) {
218   for (int Key = 0; Key < 5; ++Key)
219     this->Map[this->getKey(Key)] = this->getValue(Key);
220   TypeParam copyMap(this->Map);
221 
222   EXPECT_EQ(5u, copyMap.size());
223   for (int Key = 0; Key < 5; ++Key)
224     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
225 }
226 
227 // Test copying from a default-constructed map.
228 TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) {
229   TypeParam copyMap(this->Map);
230 
231   EXPECT_TRUE(copyMap.empty());
232 }
233 
234 // Test copying from an empty map where SmallDenseMap isn't small.
235 TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) {
236   for (int Key = 0; Key < 5; ++Key)
237     this->Map[this->getKey(Key)] = this->getValue(Key);
238   this->Map.clear();
239   TypeParam copyMap(this->Map);
240 
241   EXPECT_TRUE(copyMap.empty());
242 }
243 
244 // Test assignment operator method
245 TYPED_TEST(DenseMapTest, AssignmentTest) {
246   this->Map[this->getKey()] = this->getValue();
247   TypeParam copyMap = this->Map;
248 
249   EXPECT_EQ(1u, copyMap.size());
250   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
251 
252   // test self-assignment.
253   copyMap = static_cast<TypeParam &>(copyMap);
254   EXPECT_EQ(1u, copyMap.size());
255   EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
256 }
257 
258 TYPED_TEST(DenseMapTest, AssignmentTestNotSmall) {
259   for (int Key = 0; Key < 5; ++Key)
260     this->Map[this->getKey(Key)] = this->getValue(Key);
261   TypeParam copyMap = this->Map;
262 
263   EXPECT_EQ(5u, copyMap.size());
264   for (int Key = 0; Key < 5; ++Key)
265     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
266 
267   // test self-assignment.
268   copyMap = static_cast<TypeParam &>(copyMap);
269   EXPECT_EQ(5u, copyMap.size());
270   for (int Key = 0; Key < 5; ++Key)
271     EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
272 }
273 
274 // Test swap method
275 TYPED_TEST(DenseMapTest, SwapTest) {
276   this->Map[this->getKey()] = this->getValue();
277   TypeParam otherMap;
278 
279   this->Map.swap(otherMap);
280   EXPECT_EQ(0u, this->Map.size());
281   EXPECT_TRUE(this->Map.empty());
282   EXPECT_EQ(1u, otherMap.size());
283   EXPECT_EQ(this->getValue(), otherMap[this->getKey()]);
284 
285   this->Map.swap(otherMap);
286   EXPECT_EQ(0u, otherMap.size());
287   EXPECT_TRUE(otherMap.empty());
288   EXPECT_EQ(1u, this->Map.size());
289   EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
290 
291   // Make this more interesting by inserting 100 numbers into the map.
292   for (int i = 0; i < 100; ++i)
293     this->Map[this->getKey(i)] = this->getValue(i);
294 
295   this->Map.swap(otherMap);
296   EXPECT_EQ(0u, this->Map.size());
297   EXPECT_TRUE(this->Map.empty());
298   EXPECT_EQ(100u, otherMap.size());
299   for (int i = 0; i < 100; ++i)
300     EXPECT_EQ(this->getValue(i), otherMap[this->getKey(i)]);
301 
302   this->Map.swap(otherMap);
303   EXPECT_EQ(0u, otherMap.size());
304   EXPECT_TRUE(otherMap.empty());
305   EXPECT_EQ(100u, this->Map.size());
306   for (int i = 0; i < 100; ++i)
307     EXPECT_EQ(this->getValue(i), this->Map[this->getKey(i)]);
308 }
309 
310 // A more complex iteration test
311 TYPED_TEST(DenseMapTest, IterationTest) {
312   bool visited[100];
313   std::map<typename TypeParam::key_type, unsigned> visitedIndex;
314 
315   // Insert 100 numbers into the map
316   for (int i = 0; i < 100; ++i) {
317     visited[i] = false;
318     visitedIndex[this->getKey(i)] = i;
319 
320     this->Map[this->getKey(i)] = this->getValue(i);
321   }
322 
323   // Iterate over all numbers and mark each one found.
324   for (typename TypeParam::iterator it = this->Map.begin();
325        it != this->Map.end(); ++it)
326     visited[visitedIndex[it->first]] = true;
327 
328   // Ensure every number was visited.
329   for (int i = 0; i < 100; ++i)
330     ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
331 }
332 
333 // const_iterator test
334 TYPED_TEST(DenseMapTest, ConstIteratorTest) {
335   // Check conversion from iterator to const_iterator.
336   typename TypeParam::iterator it = this->Map.begin();
337   typename TypeParam::const_iterator cit(it);
338   EXPECT_TRUE(it == cit);
339 
340   // Check copying of const_iterators.
341   typename TypeParam::const_iterator cit2(cit);
342   EXPECT_TRUE(cit == cit2);
343 }
344 
345 namespace {
346 // Simple class that counts how many moves and copy happens when growing a map
347 struct CountCopyAndMove {
348   static int Move;
349   static int Copy;
350   CountCopyAndMove() {}
351 
352   CountCopyAndMove(const CountCopyAndMove &) { Copy++; }
353   CountCopyAndMove &operator=(const CountCopyAndMove &) {
354     Copy++;
355     return *this;
356   }
357   CountCopyAndMove(CountCopyAndMove &&) { Move++; }
358   CountCopyAndMove &operator=(const CountCopyAndMove &&) {
359     Move++;
360     return *this;
361   }
362 };
363 int CountCopyAndMove::Copy = 0;
364 int CountCopyAndMove::Move = 0;
365 
366 } // anonymous namespace
367 
368 // Test initializer list construction.
369 TEST(DenseMapCustomTest, InitializerList) {
370   DenseMap<int, int> M({{0, 0}, {0, 1}, {1, 2}});
371   EXPECT_EQ(2u, M.size());
372   EXPECT_EQ(1u, M.count(0));
373   EXPECT_EQ(0, M[0]);
374   EXPECT_EQ(1u, M.count(1));
375   EXPECT_EQ(2, M[1]);
376 }
377 
378 // Test initializer list construction.
379 TEST(DenseMapCustomTest, EqualityComparison) {
380   DenseMap<int, int> M1({{0, 0}, {1, 2}});
381   DenseMap<int, int> M2({{0, 0}, {1, 2}});
382   DenseMap<int, int> M3({{0, 0}, {1, 3}});
383 
384   EXPECT_EQ(M1, M2);
385   EXPECT_NE(M1, M3);
386 }
387 
388 // Test for the default minimum size of a DenseMap
389 TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
390   // IF THIS VALUE CHANGE, please update InitialSizeTest, InitFromIterator, and
391   // ReserveTest as well!
392   const int ExpectedInitialBucketCount = 64;
393   // Formula from DenseMap::getMinBucketToReserveForEntries()
394   const int ExpectedMaxInitialEntries = ExpectedInitialBucketCount * 3 / 4 - 1;
395 
396   DenseMap<int, CountCopyAndMove> Map;
397   // Will allocate 64 buckets
398   Map.reserve(1);
399   unsigned MemorySize = Map.getMemorySize();
400   CountCopyAndMove::Copy = 0;
401   CountCopyAndMove::Move = 0;
402   for (int i = 0; i < ExpectedMaxInitialEntries; ++i)
403     Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
404                                                 std::forward_as_tuple(i),
405                                                 std::forward_as_tuple()));
406   // Check that we didn't grow
407   EXPECT_EQ(MemorySize, Map.getMemorySize());
408   // Check that move was called the expected number of times
409   EXPECT_EQ(ExpectedMaxInitialEntries, CountCopyAndMove::Move);
410   // Check that no copy occurred
411   EXPECT_EQ(0, CountCopyAndMove::Copy);
412 
413   // Adding one extra element should grow the map
414   Map.insert(std::pair<int, CountCopyAndMove>(
415       std::piecewise_construct,
416       std::forward_as_tuple(ExpectedMaxInitialEntries),
417       std::forward_as_tuple()));
418   // Check that we grew
419   EXPECT_NE(MemorySize, Map.getMemorySize());
420   // Check that move was called the expected number of times
421   //  This relies on move-construction elision, and cannot be reliably tested.
422   //   EXPECT_EQ(ExpectedMaxInitialEntries + 2, CountCopyAndMove::Move);
423   // Check that no copy occurred
424   EXPECT_EQ(0, CountCopyAndMove::Copy);
425 }
426 
427 // Make sure creating the map with an initial size of N actually gives us enough
428 // buckets to insert N items without increasing allocation size.
429 TEST(DenseMapCustomTest, InitialSizeTest) {
430   // Test a few different sizes, 48 is *not* a random choice: we need a value
431   // that is 2/3 of a power of two to stress the grow() condition, and the power
432   // of two has to be at least 64 because of minimum size allocation in the
433   // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
434   // 64 default init.
435   for (auto Size : {1, 2, 48, 66}) {
436     DenseMap<int, CountCopyAndMove> Map(Size);
437     unsigned MemorySize = Map.getMemorySize();
438     CountCopyAndMove::Copy = 0;
439     CountCopyAndMove::Move = 0;
440     for (int i = 0; i < Size; ++i)
441       Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
442                                                   std::forward_as_tuple(i),
443                                                   std::forward_as_tuple()));
444     // Check that we didn't grow
445     EXPECT_EQ(MemorySize, Map.getMemorySize());
446     // Check that move was called the expected number of times
447     EXPECT_EQ(Size, CountCopyAndMove::Move);
448     // Check that no copy occurred
449     EXPECT_EQ(0, CountCopyAndMove::Copy);
450   }
451 }
452 
453 // Make sure creating the map with a iterator range does not trigger grow()
454 TEST(DenseMapCustomTest, InitFromIterator) {
455   std::vector<std::pair<int, CountCopyAndMove>> Values;
456   // The size is a random value greater than 64 (hardcoded DenseMap min init)
457   const int Count = 65;
458   Values.reserve(Count);
459   for (int i = 0; i < Count; i++)
460     Values.emplace_back(i, CountCopyAndMove());
461 
462   CountCopyAndMove::Move = 0;
463   CountCopyAndMove::Copy = 0;
464   DenseMap<int, CountCopyAndMove> Map(Values.begin(), Values.end());
465   // Check that no move occurred
466   EXPECT_EQ(0, CountCopyAndMove::Move);
467   // Check that copy was called the expected number of times
468   EXPECT_EQ(Count, CountCopyAndMove::Copy);
469 }
470 
471 // Make sure reserve actually gives us enough buckets to insert N items
472 // without increasing allocation size.
473 TEST(DenseMapCustomTest, ReserveTest) {
474   // Test a few different size, 48 is *not* a random choice: we need a value
475   // that is 2/3 of a power of two to stress the grow() condition, and the power
476   // of two has to be at least 64 because of minimum size allocation in the
477   // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
478   // 64 default init.
479   for (auto Size : {1, 2, 48, 66}) {
480     DenseMap<int, CountCopyAndMove> Map;
481     Map.reserve(Size);
482     unsigned MemorySize = Map.getMemorySize();
483     CountCopyAndMove::Copy = 0;
484     CountCopyAndMove::Move = 0;
485     for (int i = 0; i < Size; ++i)
486       Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
487                                                   std::forward_as_tuple(i),
488                                                   std::forward_as_tuple()));
489     // Check that we didn't grow
490     EXPECT_EQ(MemorySize, Map.getMemorySize());
491     // Check that move was called the expected number of times
492     EXPECT_EQ(Size, CountCopyAndMove::Move);
493     // Check that no copy occurred
494     EXPECT_EQ(0, CountCopyAndMove::Copy);
495   }
496 }
497 
498 // Make sure DenseMap works with StringRef keys.
499 TEST(DenseMapCustomTest, StringRefTest) {
500   DenseMap<StringRef, int> M;
501 
502   M["a"] = 1;
503   M["b"] = 2;
504   M["c"] = 3;
505 
506   EXPECT_EQ(3u, M.size());
507   EXPECT_EQ(1, M.lookup("a"));
508   EXPECT_EQ(2, M.lookup("b"));
509   EXPECT_EQ(3, M.lookup("c"));
510 
511   EXPECT_EQ(0, M.lookup("q"));
512 
513   // Test the empty string, spelled various ways.
514   EXPECT_EQ(0, M.lookup(""));
515   EXPECT_EQ(0, M.lookup(StringRef()));
516   EXPECT_EQ(0, M.lookup(StringRef("a", 0)));
517   M[""] = 42;
518   EXPECT_EQ(42, M.lookup(""));
519   EXPECT_EQ(42, M.lookup(StringRef()));
520   EXPECT_EQ(42, M.lookup(StringRef("a", 0)));
521 }
522 
523 // Key traits that allows lookup with either an unsigned or char* key;
524 // In the latter case, "a" == 0, "b" == 1 and so on.
525 struct TestDenseMapInfo {
526   static inline unsigned getEmptyKey() { return ~0; }
527   static inline unsigned getTombstoneKey() { return ~0U - 1; }
528   static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
529   static unsigned getHashValue(const char* Val) {
530     return (unsigned)(Val[0] - 'a') * 37U;
531   }
532   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
533     return LHS == RHS;
534   }
535   static bool isEqual(const char* LHS, const unsigned& RHS) {
536     return (unsigned)(LHS[0] - 'a') == RHS;
537   }
538 };
539 
540 // find_as() tests
541 TEST(DenseMapCustomTest, FindAsTest) {
542   DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
543   map[0] = 1;
544   map[1] = 2;
545   map[2] = 3;
546 
547   // Size tests
548   EXPECT_EQ(3u, map.size());
549 
550   // Normal lookup tests
551   EXPECT_EQ(1u, map.count(1));
552   EXPECT_EQ(1u, map.find(0)->second);
553   EXPECT_EQ(2u, map.find(1)->second);
554   EXPECT_EQ(3u, map.find(2)->second);
555   EXPECT_TRUE(map.find(3) == map.end());
556 
557   // find_as() tests
558   EXPECT_EQ(1u, map.find_as("a")->second);
559   EXPECT_EQ(2u, map.find_as("b")->second);
560   EXPECT_EQ(3u, map.find_as("c")->second);
561   EXPECT_TRUE(map.find_as("d") == map.end());
562 }
563 
564 TEST(DenseMapCustomTest, SmallDenseMapInitializerList) {
565   SmallDenseMap<int, int> M = {{0, 0}, {0, 1}, {1, 2}};
566   EXPECT_EQ(2u, M.size());
567   EXPECT_EQ(1u, M.count(0));
568   EXPECT_EQ(0, M[0]);
569   EXPECT_EQ(1u, M.count(1));
570   EXPECT_EQ(2, M[1]);
571 }
572 
573 struct ContiguousDenseMapInfo {
574   static inline unsigned getEmptyKey() { return ~0; }
575   static inline unsigned getTombstoneKey() { return ~0U - 1; }
576   static unsigned getHashValue(const unsigned& Val) { return Val; }
577   static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
578     return LHS == RHS;
579   }
580 };
581 
582 // Test that filling a small dense map with exactly the number of elements in
583 // the map grows to have enough space for an empty bucket.
584 TEST(DenseMapCustomTest, SmallDenseMapGrowTest) {
585   SmallDenseMap<unsigned, unsigned, 32, ContiguousDenseMapInfo> map;
586   // Add some number of elements, then delete a few to leave us some tombstones.
587   // If we just filled the map with 32 elements we'd grow because of not enough
588   // tombstones which masks the issue here.
589   for (unsigned i = 0; i < 20; ++i)
590     map[i] = i + 1;
591   for (unsigned i = 0; i < 10; ++i)
592     map.erase(i);
593   for (unsigned i = 20; i < 32; ++i)
594     map[i] = i + 1;
595 
596   // Size tests
597   EXPECT_EQ(22u, map.size());
598 
599   // Try to find an element which doesn't exist.  There was a bug in
600   // SmallDenseMap which led to a map with num elements == small capacity not
601   // having an empty bucket any more.  Finding an element not in the map would
602   // therefore never terminate.
603   EXPECT_TRUE(map.find(32) == map.end());
604 }
605 
606 TEST(DenseMapCustomTest, LargeSmallDenseMapCompaction) {
607   SmallDenseMap<unsigned, unsigned, 128, ContiguousDenseMapInfo> map;
608   // Fill to < 3/4 load.
609   for (unsigned i = 0; i < 95; ++i)
610     map[i] = i;
611   // And erase, leaving behind tombstones.
612   for (unsigned i = 0; i < 95; ++i)
613     map.erase(i);
614   // Fill further, so that less than 1/8 are empty, but still below 3/4 load.
615   for (unsigned i = 95; i < 128; ++i)
616     map[i] = i;
617 
618   EXPECT_EQ(33u, map.size());
619   // Similar to the previous test, check for a non-existing element, as an
620   // indirect check that tombstones have been removed.
621   EXPECT_TRUE(map.find(0) == map.end());
622 }
623 
624 TEST(DenseMapCustomTest, SmallDenseMapWithNumBucketsNonPowerOf2) {
625   // Is not power of 2.
626   const unsigned NumInitBuckets = 33;
627   // Power of 2 less then NumInitBuckets.
628   constexpr unsigned InlineBuckets = 4;
629   // Constructor should not trigger assert.
630   SmallDenseMap<int, int, InlineBuckets> map(NumInitBuckets);
631 }
632 
633 TEST(DenseMapCustomTest, TryEmplaceTest) {
634   DenseMap<int, std::unique_ptr<int>> Map;
635   std::unique_ptr<int> P(new int(2));
636   auto Try1 = Map.try_emplace(0, new int(1));
637   EXPECT_TRUE(Try1.second);
638   auto Try2 = Map.try_emplace(0, std::move(P));
639   EXPECT_FALSE(Try2.second);
640   EXPECT_EQ(Try1.first, Try2.first);
641   EXPECT_NE(nullptr, P);
642 }
643 
644 TEST(DenseMapCustomTest, ConstTest) {
645   // Test that const pointers work okay for count and find, even when the
646   // underlying map is a non-const pointer.
647   DenseMap<int *, int> Map;
648   int A;
649   int *B = &A;
650   const int *C = &A;
651   Map.insert({B, 0});
652   EXPECT_EQ(Map.count(B), 1u);
653   EXPECT_EQ(Map.count(C), 1u);
654   EXPECT_NE(Map.find(B), Map.end());
655   EXPECT_NE(Map.find(C), Map.end());
656 }
657 
658 struct IncompleteStruct;
659 
660 TEST(DenseMapCustomTest, OpaquePointerKey) {
661   // Test that we can use a pointer to an incomplete type as a DenseMap key.
662   // This is an important build time optimization, since many classes have
663   // DenseMap members.
664   DenseMap<IncompleteStruct *, int> Map;
665   int Keys[3] = {0, 0, 0};
666   IncompleteStruct *K1 = reinterpret_cast<IncompleteStruct *>(&Keys[0]);
667   IncompleteStruct *K2 = reinterpret_cast<IncompleteStruct *>(&Keys[1]);
668   IncompleteStruct *K3 = reinterpret_cast<IncompleteStruct *>(&Keys[2]);
669   Map.insert({K1, 1});
670   Map.insert({K2, 2});
671   Map.insert({K3, 3});
672   EXPECT_EQ(Map.count(K1), 1u);
673   EXPECT_EQ(Map[K1], 1);
674   EXPECT_EQ(Map[K2], 2);
675   EXPECT_EQ(Map[K3], 3);
676   Map.clear();
677   EXPECT_EQ(Map.find(K1), Map.end());
678   EXPECT_EQ(Map.find(K2), Map.end());
679   EXPECT_EQ(Map.find(K3), Map.end());
680 }
681 } // namespace
682 
683 namespace {
684 struct A {
685   A(int value) : value(value) {}
686   int value;
687 };
688 struct B : public A {
689   using A::A;
690 };
691 } // namespace
692 
693 namespace llvm {
694 template <typename T>
695 struct DenseMapInfo<T, std::enable_if_t<std::is_base_of_v<A, T>>> {
696   static inline T getEmptyKey() { return {static_cast<int>(~0)}; }
697   static inline T getTombstoneKey() { return {static_cast<int>(~0U - 1)}; }
698   static unsigned getHashValue(const T &Val) { return Val.value; }
699   static bool isEqual(const T &LHS, const T &RHS) {
700     return LHS.value == RHS.value;
701   }
702 };
703 } // namespace llvm
704 
705 namespace {
706 TEST(DenseMapCustomTest, SFINAEMapInfo) {
707   // Test that we can use a pointer to an incomplete type as a DenseMap key.
708   // This is an important build time optimization, since many classes have
709   // DenseMap members.
710   DenseMap<B, int> Map;
711   B Keys[3] = {{0}, {1}, {2}};
712   Map.insert({Keys[0], 1});
713   Map.insert({Keys[1], 2});
714   Map.insert({Keys[2], 3});
715   EXPECT_EQ(Map.count(Keys[0]), 1u);
716   EXPECT_EQ(Map[Keys[0]], 1);
717   EXPECT_EQ(Map[Keys[1]], 2);
718   EXPECT_EQ(Map[Keys[2]], 3);
719   Map.clear();
720   EXPECT_EQ(Map.find(Keys[0]), Map.end());
721   EXPECT_EQ(Map.find(Keys[1]), Map.end());
722   EXPECT_EQ(Map.find(Keys[2]), Map.end());
723 }
724 
725 TEST(DenseMapCustomTest, VariantSupport) {
726   using variant = std::variant<int, int>;
727   DenseMap<variant, int> Map;
728   variant Keys[] = {
729       variant(std::in_place_index<0>, 1),
730       variant(std::in_place_index<1>, 1),
731   };
732   Map.try_emplace(Keys[0], 0);
733   Map.try_emplace(Keys[1], 1);
734   EXPECT_THAT(Map, testing::SizeIs(2));
735   EXPECT_NE(DenseMapInfo<variant>::getHashValue(Keys[0]),
736             DenseMapInfo<variant>::getHashValue(Keys[1]));
737 }
738 } // namespace
739