xref: /llvm-project/llvm/unittests/ADT/StringMapTest.cpp (revision 5f290c090a2404238a5b0ae4233f3ae9daec319e)
1 //===- llvm/unittest/ADT/StringMapMap.cpp - StringMap 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/StringMap.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Support/DataTypes.h"
13 #include "gtest/gtest.h"
14 #include <limits>
15 #include <tuple>
16 using namespace llvm;
17 
18 namespace {
19 
20 // Test fixture
21 class StringMapTest : public testing::Test {
22 protected:
23   StringMap<uint32_t> testMap;
24 
25   static const char testKey[];
26   static const uint32_t testValue;
27   static const char* testKeyFirst;
28   static size_t testKeyLength;
29   static const std::string testKeyStr;
30 
31   void assertEmptyMap() {
32     // Size tests
33     EXPECT_EQ(0u, testMap.size());
34     EXPECT_TRUE(testMap.empty());
35 
36     // Iterator tests
37     EXPECT_TRUE(testMap.begin() == testMap.end());
38 
39     // Lookup tests
40     EXPECT_EQ(0u, testMap.count(testKey));
41     EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
42     EXPECT_EQ(0u, testMap.count(testKeyStr));
43     EXPECT_TRUE(testMap.find(testKey) == testMap.end());
44     EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
45                 testMap.end());
46     EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
47   }
48 
49   void assertSingleItemMap() {
50     // Size tests
51     EXPECT_EQ(1u, testMap.size());
52     EXPECT_FALSE(testMap.begin() == testMap.end());
53     EXPECT_FALSE(testMap.empty());
54 
55     // Iterator tests
56     StringMap<uint32_t>::iterator it = testMap.begin();
57     EXPECT_STREQ(testKey, it->first().data());
58     EXPECT_EQ(testValue, it->second);
59     ++it;
60     EXPECT_TRUE(it == testMap.end());
61 
62     // Lookup tests
63     EXPECT_EQ(1u, testMap.count(testKey));
64     EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
65     EXPECT_EQ(1u, testMap.count(testKeyStr));
66     EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
67     EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
68                 testMap.begin());
69     EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
70   }
71 };
72 
73 const char StringMapTest::testKey[] = "key";
74 const uint32_t StringMapTest::testValue = 1u;
75 const char* StringMapTest::testKeyFirst = testKey;
76 size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
77 const std::string StringMapTest::testKeyStr(testKey);
78 
79 struct CountCopyAndMove {
80   CountCopyAndMove() = default;
81   CountCopyAndMove(const CountCopyAndMove &) { copy = 1; }
82   CountCopyAndMove(CountCopyAndMove &&) { move = 1; }
83   void operator=(const CountCopyAndMove &) { ++copy; }
84   void operator=(CountCopyAndMove &&) { ++move; }
85   int copy = 0;
86   int move = 0;
87 };
88 
89 // Empty map tests.
90 TEST_F(StringMapTest, EmptyMapTest) {
91   assertEmptyMap();
92 }
93 
94 // Constant map tests.
95 TEST_F(StringMapTest, ConstEmptyMapTest) {
96   const StringMap<uint32_t>& constTestMap = testMap;
97 
98   // Size tests
99   EXPECT_EQ(0u, constTestMap.size());
100   EXPECT_TRUE(constTestMap.empty());
101 
102   // Iterator tests
103   EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
104 
105   // Lookup tests
106   EXPECT_EQ(0u, constTestMap.count(testKey));
107   EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
108   EXPECT_EQ(0u, constTestMap.count(testKeyStr));
109   EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
110   EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
111               constTestMap.end());
112   EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
113 }
114 
115 // initializer_list ctor test; also implicitly tests initializer_list and
116 // iterator overloads of insert().
117 TEST_F(StringMapTest, InitializerListCtor) {
118   testMap = StringMap<uint32_t>({{"key", 1}});
119   assertSingleItemMap();
120 }
121 
122 // A map with a single entry.
123 TEST_F(StringMapTest, SingleEntryMapTest) {
124   testMap[testKey] = testValue;
125   assertSingleItemMap();
126 }
127 
128 // Test clear() method.
129 TEST_F(StringMapTest, ClearTest) {
130   testMap[testKey] = testValue;
131   testMap.clear();
132   assertEmptyMap();
133 }
134 
135 // Test erase(iterator) method.
136 TEST_F(StringMapTest, EraseIteratorTest) {
137   testMap[testKey] = testValue;
138   testMap.erase(testMap.begin());
139   assertEmptyMap();
140 }
141 
142 // Test erase(value) method.
143 TEST_F(StringMapTest, EraseValueTest) {
144   testMap[testKey] = testValue;
145   testMap.erase(testKey);
146   assertEmptyMap();
147 }
148 
149 // Test inserting two values and erasing one.
150 TEST_F(StringMapTest, InsertAndEraseTest) {
151   testMap[testKey] = testValue;
152   testMap["otherKey"] = 2;
153   testMap.erase("otherKey");
154   assertSingleItemMap();
155 }
156 
157 TEST_F(StringMapTest, SmallFullMapTest) {
158   // StringMap has a tricky corner case when the map is small (<8 buckets) and
159   // it fills up through a balanced pattern of inserts and erases. This can
160   // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
161   llvm::StringMap<int> Map(2);
162 
163   Map["eins"] = 1;
164   Map["zwei"] = 2;
165   Map["drei"] = 3;
166   Map.erase("drei");
167   Map.erase("eins");
168   Map["veir"] = 4;
169   Map["funf"] = 5;
170 
171   EXPECT_EQ(3u, Map.size());
172   EXPECT_EQ(0, Map.lookup("eins"));
173   EXPECT_EQ(2, Map.lookup("zwei"));
174   EXPECT_EQ(0, Map.lookup("drei"));
175   EXPECT_EQ(4, Map.lookup("veir"));
176   EXPECT_EQ(5, Map.lookup("funf"));
177 }
178 
179 TEST_F(StringMapTest, CopyCtorTest) {
180   llvm::StringMap<int> Map;
181 
182   Map["eins"] = 1;
183   Map["zwei"] = 2;
184   Map["drei"] = 3;
185   Map.erase("drei");
186   Map.erase("eins");
187   Map["veir"] = 4;
188   Map["funf"] = 5;
189 
190   EXPECT_EQ(3u, Map.size());
191   EXPECT_EQ(0, Map.lookup("eins"));
192   EXPECT_EQ(2, Map.lookup("zwei"));
193   EXPECT_EQ(0, Map.lookup("drei"));
194   EXPECT_EQ(4, Map.lookup("veir"));
195   EXPECT_EQ(5, Map.lookup("funf"));
196 
197   llvm::StringMap<int> Map2(Map);
198   EXPECT_EQ(3u, Map2.size());
199   EXPECT_EQ(0, Map2.lookup("eins"));
200   EXPECT_EQ(2, Map2.lookup("zwei"));
201   EXPECT_EQ(0, Map2.lookup("drei"));
202   EXPECT_EQ(4, Map2.lookup("veir"));
203   EXPECT_EQ(5, Map2.lookup("funf"));
204 }
205 
206 // A more complex iteration test.
207 TEST_F(StringMapTest, IterationTest) {
208   bool visited[100];
209 
210   // Insert 100 numbers into the map
211   for (int i = 0; i < 100; ++i) {
212     std::stringstream ss;
213     ss << "key_" << i;
214     testMap[ss.str()] = i;
215     visited[i] = false;
216   }
217 
218   // Iterate over all numbers and mark each one found.
219   for (StringMap<uint32_t>::iterator it = testMap.begin();
220       it != testMap.end(); ++it) {
221     std::stringstream ss;
222     ss << "key_" << it->second;
223     ASSERT_STREQ(ss.str().c_str(), it->first().data());
224     visited[it->second] = true;
225   }
226 
227   // Ensure every number was visited.
228   for (int i = 0; i < 100; ++i) {
229     ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
230   }
231 }
232 
233 // Test StringMapEntry::Create() method.
234 TEST_F(StringMapTest, StringMapEntryTest) {
235   MallocAllocator Allocator;
236   StringMap<uint32_t>::value_type *entry =
237       StringMap<uint32_t>::value_type::Create(
238           StringRef(testKeyFirst, testKeyLength), Allocator, 1u);
239   EXPECT_STREQ(testKey, entry->first().data());
240   EXPECT_EQ(1u, entry->second);
241   entry->Destroy(Allocator);
242 }
243 
244 // Test insert() method.
245 TEST_F(StringMapTest, InsertTest) {
246   SCOPED_TRACE("InsertTest");
247   testMap.insert(
248       StringMap<uint32_t>::value_type::Create(
249           StringRef(testKeyFirst, testKeyLength),
250           testMap.getAllocator(), 1u));
251   assertSingleItemMap();
252 }
253 
254 // Test insert(pair<K, V>) method
255 TEST_F(StringMapTest, InsertPairTest) {
256   bool Inserted;
257   StringMap<uint32_t>::iterator NewIt;
258   std::tie(NewIt, Inserted) =
259       testMap.insert(std::make_pair(testKeyFirst, testValue));
260   EXPECT_EQ(1u, testMap.size());
261   EXPECT_EQ(testValue, testMap[testKeyFirst]);
262   EXPECT_EQ(testKeyFirst, NewIt->first());
263   EXPECT_EQ(testValue, NewIt->second);
264   EXPECT_TRUE(Inserted);
265 
266   StringMap<uint32_t>::iterator ExistingIt;
267   std::tie(ExistingIt, Inserted) =
268       testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
269   EXPECT_EQ(1u, testMap.size());
270   EXPECT_EQ(testValue, testMap[testKeyFirst]);
271   EXPECT_FALSE(Inserted);
272   EXPECT_EQ(NewIt, ExistingIt);
273 }
274 
275 // Test insert(pair<K, V>) method when rehashing occurs
276 TEST_F(StringMapTest, InsertRehashingPairTest) {
277   // Check that the correct iterator is returned when the inserted element is
278   // moved to a different bucket during internal rehashing. This depends on
279   // the particular key, and the implementation of StringMap and HashString.
280   // Changes to those might result in this test not actually checking that.
281   StringMap<uint32_t> t(0);
282   EXPECT_EQ(0u, t.getNumBuckets());
283 
284   StringMap<uint32_t>::iterator It =
285     t.insert(std::make_pair("abcdef", 42)).first;
286   EXPECT_EQ(16u, t.getNumBuckets());
287   EXPECT_EQ("abcdef", It->first());
288   EXPECT_EQ(42u, It->second);
289 }
290 
291 TEST_F(StringMapTest, InsertOrAssignTest) {
292   struct A : CountCopyAndMove {
293     A(int v) : v(v) {}
294     int v;
295   };
296   StringMap<A> t(0);
297 
298   auto try1 = t.insert_or_assign("A", A(1));
299   EXPECT_TRUE(try1.second);
300   EXPECT_EQ(1, try1.first->second.v);
301   EXPECT_EQ(1, try1.first->second.move);
302 
303   auto try2 = t.insert_or_assign("A", A(2));
304   EXPECT_FALSE(try2.second);
305   EXPECT_EQ(2, try2.first->second.v);
306   EXPECT_EQ(2, try1.first->second.move);
307 
308   EXPECT_EQ(try1.first, try2.first);
309   EXPECT_EQ(0, try1.first->second.copy);
310 }
311 
312 TEST_F(StringMapTest, IterMapKeysVector) {
313   StringMap<int> Map;
314   Map["A"] = 1;
315   Map["B"] = 2;
316   Map["C"] = 3;
317   Map["D"] = 3;
318 
319   std::vector<StringRef> Keys{Map.keys().begin(), Map.keys().end()};
320   llvm::sort(Keys);
321 
322   std::vector<StringRef> Expected{{"A", "B", "C", "D"}};
323   EXPECT_EQ(Expected, Keys);
324 }
325 
326 TEST_F(StringMapTest, IterMapKeysSmallVector) {
327   StringMap<int> Map;
328   Map["A"] = 1;
329   Map["B"] = 2;
330   Map["C"] = 3;
331   Map["D"] = 3;
332 
333   auto Keys = to_vector<4>(Map.keys());
334   llvm::sort(Keys);
335 
336   SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
337   EXPECT_EQ(Expected, Keys);
338 }
339 
340 // Create a non-default constructable value
341 struct StringMapTestStruct {
342   StringMapTestStruct(int i) : i(i) {}
343   StringMapTestStruct() = delete;
344   int i;
345 };
346 
347 TEST_F(StringMapTest, NonDefaultConstructable) {
348   StringMap<StringMapTestStruct> t;
349   t.insert(std::make_pair("Test", StringMapTestStruct(123)));
350   StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
351   ASSERT_NE(iter, t.end());
352   ASSERT_EQ(iter->second.i, 123);
353 }
354 
355 struct Immovable {
356   Immovable() {}
357   Immovable(Immovable&&) = delete; // will disable the other special members
358 };
359 
360 struct MoveOnly {
361   int i;
362   MoveOnly(int i) : i(i) {}
363   MoveOnly(const Immovable&) : i(0) {}
364   MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
365   MoveOnly &operator=(MoveOnly &&RHS) {
366     i = RHS.i;
367     return *this;
368   }
369 
370 private:
371   MoveOnly(const MoveOnly &) = delete;
372   MoveOnly &operator=(const MoveOnly &) = delete;
373 };
374 
375 TEST_F(StringMapTest, MoveOnly) {
376   StringMap<MoveOnly> t;
377   t.insert(std::make_pair("Test", MoveOnly(42)));
378   StringRef Key = "Test";
379   StringMapEntry<MoveOnly>::Create(Key, t.getAllocator(), MoveOnly(42))
380       ->Destroy(t.getAllocator());
381 }
382 
383 TEST_F(StringMapTest, CtorArg) {
384   StringRef Key = "Test";
385   MallocAllocator Allocator;
386   StringMapEntry<MoveOnly>::Create(Key, Allocator, Immovable())
387       ->Destroy(Allocator);
388 }
389 
390 TEST_F(StringMapTest, MoveConstruct) {
391   StringMap<int> A;
392   A["x"] = 42;
393   StringMap<int> B = std::move(A);
394   ASSERT_EQ(A.size(), 0u);
395   ASSERT_EQ(B.size(), 1u);
396   ASSERT_EQ(B["x"], 42);
397   ASSERT_EQ(B.count("y"), 0u);
398 }
399 
400 TEST_F(StringMapTest, MoveAssignment) {
401   StringMap<int> A;
402   A["x"] = 42;
403   StringMap<int> B;
404   B["y"] = 117;
405   A = std::move(B);
406   ASSERT_EQ(A.size(), 1u);
407   ASSERT_EQ(B.size(), 0u);
408   ASSERT_EQ(A["y"], 117);
409   ASSERT_EQ(B.count("x"), 0u);
410 }
411 
412 TEST_F(StringMapTest, EqualEmpty) {
413   StringMap<int> A;
414   StringMap<int> B;
415   ASSERT_TRUE(A == B);
416   ASSERT_FALSE(A != B);
417   ASSERT_TRUE(A == A); // self check
418 }
419 
420 TEST_F(StringMapTest, EqualWithValues) {
421   StringMap<int> A;
422   A["A"] = 1;
423   A["B"] = 2;
424   A["C"] = 3;
425   A["D"] = 3;
426 
427   StringMap<int> B;
428   B["A"] = 1;
429   B["B"] = 2;
430   B["C"] = 3;
431   B["D"] = 3;
432 
433   ASSERT_TRUE(A == B);
434   ASSERT_TRUE(B == A);
435   ASSERT_FALSE(A != B);
436   ASSERT_FALSE(B != A);
437   ASSERT_TRUE(A == A); // self check
438 }
439 
440 TEST_F(StringMapTest, NotEqualMissingKeys) {
441   StringMap<int> A;
442   A["A"] = 1;
443   A["B"] = 2;
444 
445   StringMap<int> B;
446   B["A"] = 1;
447   B["B"] = 2;
448   B["C"] = 3;
449   B["D"] = 3;
450 
451   ASSERT_FALSE(A == B);
452   ASSERT_FALSE(B == A);
453   ASSERT_TRUE(A != B);
454   ASSERT_TRUE(B != A);
455 }
456 
457 TEST_F(StringMapTest, NotEqualWithDifferentValues) {
458   StringMap<int> A;
459   A["A"] = 1;
460   A["B"] = 2;
461   A["C"] = 100;
462   A["D"] = 3;
463 
464   StringMap<int> B;
465   B["A"] = 1;
466   B["B"] = 2;
467   B["C"] = 3;
468   B["D"] = 3;
469 
470   ASSERT_FALSE(A == B);
471   ASSERT_FALSE(B == A);
472   ASSERT_TRUE(A != B);
473   ASSERT_TRUE(B != A);
474 }
475 
476 struct Countable {
477   int &InstanceCount;
478   int Number;
479   Countable(int Number, int &InstanceCount)
480       : InstanceCount(InstanceCount), Number(Number) {
481     ++InstanceCount;
482   }
483   Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
484     ++InstanceCount;
485     C.Number = -1;
486   }
487   Countable(const Countable &C)
488       : InstanceCount(C.InstanceCount), Number(C.Number) {
489     ++InstanceCount;
490   }
491   Countable &operator=(Countable C) {
492     Number = C.Number;
493     return *this;
494   }
495   ~Countable() { --InstanceCount; }
496 };
497 
498 TEST_F(StringMapTest, MoveDtor) {
499   int InstanceCount = 0;
500   StringMap<Countable> A;
501   A.insert(std::make_pair("x", Countable(42, InstanceCount)));
502   ASSERT_EQ(InstanceCount, 1);
503   auto I = A.find("x");
504   ASSERT_NE(I, A.end());
505   ASSERT_EQ(I->second.Number, 42);
506 
507   StringMap<Countable> B;
508   B = std::move(A);
509   ASSERT_EQ(InstanceCount, 1);
510   ASSERT_TRUE(A.empty());
511   I = B.find("x");
512   ASSERT_NE(I, B.end());
513   ASSERT_EQ(I->second.Number, 42);
514 
515   B = StringMap<Countable>();
516   ASSERT_EQ(InstanceCount, 0);
517   ASSERT_TRUE(B.empty());
518 }
519 
520 namespace {
521 // Simple class that counts how many moves and copy happens when growing a map
522 struct CountCtorCopyAndMove {
523   static unsigned Ctor;
524   static unsigned Move;
525   static unsigned Copy;
526   int Data = 0;
527   CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
528   CountCtorCopyAndMove() { Ctor++; }
529 
530   CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
531   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
532     Copy++;
533     return *this;
534   }
535   CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
536   CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
537     Move++;
538     return *this;
539   }
540 };
541 unsigned CountCtorCopyAndMove::Copy = 0;
542 unsigned CountCtorCopyAndMove::Move = 0;
543 unsigned CountCtorCopyAndMove::Ctor = 0;
544 
545 } // anonymous namespace
546 
547 // Make sure creating the map with an initial size of N actually gives us enough
548 // buckets to insert N items without increasing allocation size.
549 TEST(StringMapCustomTest, InitialSizeTest) {
550   // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
551   // arbitrary prime, picked without any good reason.
552   for (auto Size : {1, 32, 67}) {
553     StringMap<CountCtorCopyAndMove> Map(Size);
554     auto NumBuckets = Map.getNumBuckets();
555     CountCtorCopyAndMove::Move = 0;
556     CountCtorCopyAndMove::Copy = 0;
557     for (int i = 0; i < Size; ++i)
558       Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
559           std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
560           std::forward_as_tuple(i)));
561     // After the initial move, the map will move the Elts in the Entry.
562     EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
563     // We copy once the pair from the Elts vector
564     EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
565     // Check that the map didn't grow
566     EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
567   }
568 }
569 
570 TEST(StringMapCustomTest, BracketOperatorCtor) {
571   StringMap<CountCtorCopyAndMove> Map;
572   CountCtorCopyAndMove::Ctor = 0;
573   Map["abcd"];
574   EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
575   // Test that operator[] does not create a value when it is already in the map
576   CountCtorCopyAndMove::Ctor = 0;
577   Map["abcd"];
578   EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
579 }
580 
581 namespace {
582 struct NonMoveableNonCopyableType {
583   int Data = 0;
584   NonMoveableNonCopyableType() = default;
585   NonMoveableNonCopyableType(int Data) : Data(Data) {}
586   NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
587   NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
588 };
589 }
590 
591 // Test that we can "emplace" an element in the map without involving map/move
592 TEST(StringMapCustomTest, EmplaceTest) {
593   StringMap<NonMoveableNonCopyableType> Map;
594   Map.try_emplace("abcd", 42);
595   EXPECT_EQ(1u, Map.count("abcd"));
596   EXPECT_EQ(42, Map["abcd"].Data);
597 }
598 
599 // Test that StringMapEntryBase can handle size_t wide sizes.
600 TEST(StringMapCustomTest, StringMapEntryBaseSize) {
601   size_t LargeValue;
602 
603   // Test that the entry can represent max-unsigned.
604   if (sizeof(size_t) <= sizeof(unsigned))
605     LargeValue = std::numeric_limits<unsigned>::max();
606   else
607     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
608   StringMapEntryBase LargeBase(LargeValue);
609   EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
610 
611   // Test that the entry can hold at least max size_t.
612   LargeValue = std::numeric_limits<size_t>::max();
613   StringMapEntryBase LargerBase(LargeValue);
614   LargeValue = std::numeric_limits<size_t>::max();
615   EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
616 }
617 
618 // Test that StringMapEntry can handle size_t wide sizes.
619 TEST(StringMapCustomTest, StringMapEntrySize) {
620   size_t LargeValue;
621 
622   // Test that the entry can represent max-unsigned.
623   if (sizeof(size_t) <= sizeof(unsigned))
624     LargeValue = std::numeric_limits<unsigned>::max();
625   else
626     LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
627   StringMapEntry<int> LargeEntry(LargeValue);
628   StringRef Key = LargeEntry.getKey();
629   EXPECT_EQ(LargeValue, Key.size());
630 
631   // Test that the entry can hold at least max size_t.
632   LargeValue = std::numeric_limits<size_t>::max();
633   StringMapEntry<int> LargerEntry(LargeValue);
634   Key = LargerEntry.getKey();
635   EXPECT_EQ(LargeValue, Key.size());
636 }
637 
638 } // end anonymous namespace
639