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