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