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