1 //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===// 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 // SmallVector unit tests. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "llvm/ADT/SmallVector.h" 14 #include "llvm/ADT/ArrayRef.h" 15 #include "llvm/Support/Compiler.h" 16 #include "gtest/gtest.h" 17 #include <list> 18 #include <stdarg.h> 19 20 using namespace llvm; 21 22 namespace { 23 24 /// A helper class that counts the total number of constructor and 25 /// destructor calls. 26 class Constructable { 27 private: 28 static int numConstructorCalls; 29 static int numMoveConstructorCalls; 30 static int numCopyConstructorCalls; 31 static int numDestructorCalls; 32 static int numAssignmentCalls; 33 static int numMoveAssignmentCalls; 34 static int numCopyAssignmentCalls; 35 36 bool constructed; 37 int value; 38 39 public: 40 Constructable() : constructed(true), value(0) { 41 ++numConstructorCalls; 42 } 43 44 Constructable(int val) : constructed(true), value(val) { 45 ++numConstructorCalls; 46 } 47 48 Constructable(const Constructable & src) : constructed(true) { 49 value = src.value; 50 ++numConstructorCalls; 51 ++numCopyConstructorCalls; 52 } 53 54 Constructable(Constructable && src) : constructed(true) { 55 value = src.value; 56 ++numConstructorCalls; 57 ++numMoveConstructorCalls; 58 } 59 60 ~Constructable() { 61 EXPECT_TRUE(constructed); 62 ++numDestructorCalls; 63 constructed = false; 64 } 65 66 Constructable & operator=(const Constructable & src) { 67 EXPECT_TRUE(constructed); 68 value = src.value; 69 ++numAssignmentCalls; 70 ++numCopyAssignmentCalls; 71 return *this; 72 } 73 74 Constructable & operator=(Constructable && src) { 75 EXPECT_TRUE(constructed); 76 value = src.value; 77 ++numAssignmentCalls; 78 ++numMoveAssignmentCalls; 79 return *this; 80 } 81 82 int getValue() const { 83 return abs(value); 84 } 85 86 static void reset() { 87 numConstructorCalls = 0; 88 numMoveConstructorCalls = 0; 89 numCopyConstructorCalls = 0; 90 numDestructorCalls = 0; 91 numAssignmentCalls = 0; 92 numMoveAssignmentCalls = 0; 93 numCopyAssignmentCalls = 0; 94 } 95 96 static int getNumConstructorCalls() { 97 return numConstructorCalls; 98 } 99 100 static int getNumMoveConstructorCalls() { 101 return numMoveConstructorCalls; 102 } 103 104 static int getNumCopyConstructorCalls() { 105 return numCopyConstructorCalls; 106 } 107 108 static int getNumDestructorCalls() { 109 return numDestructorCalls; 110 } 111 112 static int getNumAssignmentCalls() { 113 return numAssignmentCalls; 114 } 115 116 static int getNumMoveAssignmentCalls() { 117 return numMoveAssignmentCalls; 118 } 119 120 static int getNumCopyAssignmentCalls() { 121 return numCopyAssignmentCalls; 122 } 123 124 friend bool operator==(const Constructable & c0, const Constructable & c1) { 125 return c0.getValue() == c1.getValue(); 126 } 127 128 friend bool LLVM_ATTRIBUTE_UNUSED 129 operator!=(const Constructable & c0, const Constructable & c1) { 130 return c0.getValue() != c1.getValue(); 131 } 132 }; 133 134 int Constructable::numConstructorCalls; 135 int Constructable::numCopyConstructorCalls; 136 int Constructable::numMoveConstructorCalls; 137 int Constructable::numDestructorCalls; 138 int Constructable::numAssignmentCalls; 139 int Constructable::numCopyAssignmentCalls; 140 int Constructable::numMoveAssignmentCalls; 141 142 struct NonCopyable { 143 NonCopyable() {} 144 NonCopyable(NonCopyable &&) {} 145 NonCopyable &operator=(NonCopyable &&) { return *this; } 146 private: 147 NonCopyable(const NonCopyable &) = delete; 148 NonCopyable &operator=(const NonCopyable &) = delete; 149 }; 150 151 LLVM_ATTRIBUTE_USED void CompileTest() { 152 SmallVector<NonCopyable, 0> V; 153 V.resize(42); 154 } 155 156 class SmallVectorTestBase : public testing::Test { 157 protected: 158 void SetUp() override { Constructable::reset(); } 159 160 template <typename VectorT> 161 void assertEmpty(VectorT & v) { 162 // Size tests 163 EXPECT_EQ(0u, v.size()); 164 EXPECT_TRUE(v.empty()); 165 166 // Iterator tests 167 EXPECT_TRUE(v.begin() == v.end()); 168 } 169 170 // Assert that v contains the specified values, in order. 171 template <typename VectorT> 172 void assertValuesInOrder(VectorT & v, size_t size, ...) { 173 EXPECT_EQ(size, v.size()); 174 175 va_list ap; 176 va_start(ap, size); 177 for (size_t i = 0; i < size; ++i) { 178 int value = va_arg(ap, int); 179 EXPECT_EQ(value, v[i].getValue()); 180 } 181 182 va_end(ap); 183 } 184 185 // Generate a sequence of values to initialize the vector. 186 template <typename VectorT> 187 void makeSequence(VectorT & v, int start, int end) { 188 for (int i = start; i <= end; ++i) { 189 v.push_back(Constructable(i)); 190 } 191 } 192 }; 193 194 // Test fixture class 195 template <typename VectorT> 196 class SmallVectorTest : public SmallVectorTestBase { 197 protected: 198 VectorT theVector; 199 VectorT otherVector; 200 }; 201 202 203 typedef ::testing::Types<SmallVector<Constructable, 0>, 204 SmallVector<Constructable, 1>, 205 SmallVector<Constructable, 2>, 206 SmallVector<Constructable, 4>, 207 SmallVector<Constructable, 5> 208 > SmallVectorTestTypes; 209 TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes); 210 211 // Constructor test. 212 TYPED_TEST(SmallVectorTest, ConstructorNonIterTest) { 213 SCOPED_TRACE("ConstructorTest"); 214 this->theVector = SmallVector<Constructable, 2>(2, 2); 215 this->assertValuesInOrder(this->theVector, 2u, 2, 2); 216 } 217 218 // Constructor test. 219 TYPED_TEST(SmallVectorTest, ConstructorIterTest) { 220 SCOPED_TRACE("ConstructorTest"); 221 int arr[] = {1, 2, 3}; 222 this->theVector = 223 SmallVector<Constructable, 4>(std::begin(arr), std::end(arr)); 224 this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); 225 } 226 227 // New vector test. 228 TYPED_TEST(SmallVectorTest, EmptyVectorTest) { 229 SCOPED_TRACE("EmptyVectorTest"); 230 this->assertEmpty(this->theVector); 231 EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend()); 232 EXPECT_EQ(0, Constructable::getNumConstructorCalls()); 233 EXPECT_EQ(0, Constructable::getNumDestructorCalls()); 234 } 235 236 // Simple insertions and deletions. 237 TYPED_TEST(SmallVectorTest, PushPopTest) { 238 SCOPED_TRACE("PushPopTest"); 239 240 // Track whether the vector will potentially have to grow. 241 bool RequiresGrowth = this->theVector.capacity() < 3; 242 243 // Push an element 244 this->theVector.push_back(Constructable(1)); 245 246 // Size tests 247 this->assertValuesInOrder(this->theVector, 1u, 1); 248 EXPECT_FALSE(this->theVector.begin() == this->theVector.end()); 249 EXPECT_FALSE(this->theVector.empty()); 250 251 // Push another element 252 this->theVector.push_back(Constructable(2)); 253 this->assertValuesInOrder(this->theVector, 2u, 1, 2); 254 255 // Insert at beginning. Reserve space to avoid reference invalidation from 256 // this->theVector[1]. 257 this->theVector.reserve(this->theVector.size() + 1); 258 this->theVector.insert(this->theVector.begin(), this->theVector[1]); 259 this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2); 260 261 // Pop one element 262 this->theVector.pop_back(); 263 this->assertValuesInOrder(this->theVector, 2u, 2, 1); 264 265 // Pop remaining elements 266 this->theVector.pop_back_n(2); 267 this->assertEmpty(this->theVector); 268 269 // Check number of constructor calls. Should be 2 for each list element, 270 // one for the argument to push_back, one for the argument to insert, 271 // and one for the list element itself. 272 if (!RequiresGrowth) { 273 EXPECT_EQ(5, Constructable::getNumConstructorCalls()); 274 EXPECT_EQ(5, Constructable::getNumDestructorCalls()); 275 } else { 276 // If we had to grow the vector, these only have a lower bound, but should 277 // always be equal. 278 EXPECT_LE(5, Constructable::getNumConstructorCalls()); 279 EXPECT_EQ(Constructable::getNumConstructorCalls(), 280 Constructable::getNumDestructorCalls()); 281 } 282 } 283 284 // Clear test. 285 TYPED_TEST(SmallVectorTest, ClearTest) { 286 SCOPED_TRACE("ClearTest"); 287 288 this->theVector.reserve(2); 289 this->makeSequence(this->theVector, 1, 2); 290 this->theVector.clear(); 291 292 this->assertEmpty(this->theVector); 293 EXPECT_EQ(4, Constructable::getNumConstructorCalls()); 294 EXPECT_EQ(4, Constructable::getNumDestructorCalls()); 295 } 296 297 // Resize smaller test. 298 TYPED_TEST(SmallVectorTest, ResizeShrinkTest) { 299 SCOPED_TRACE("ResizeShrinkTest"); 300 301 this->theVector.reserve(3); 302 this->makeSequence(this->theVector, 1, 3); 303 this->theVector.resize(1); 304 305 this->assertValuesInOrder(this->theVector, 1u, 1); 306 EXPECT_EQ(6, Constructable::getNumConstructorCalls()); 307 EXPECT_EQ(5, Constructable::getNumDestructorCalls()); 308 } 309 310 // Resize bigger test. 311 TYPED_TEST(SmallVectorTest, ResizeGrowTest) { 312 SCOPED_TRACE("ResizeGrowTest"); 313 314 this->theVector.resize(2); 315 316 EXPECT_EQ(2, Constructable::getNumConstructorCalls()); 317 EXPECT_EQ(0, Constructable::getNumDestructorCalls()); 318 EXPECT_EQ(2u, this->theVector.size()); 319 } 320 321 TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) { 322 this->theVector.resize(2); 323 324 Constructable::reset(); 325 326 this->theVector.resize(4); 327 328 size_t Ctors = Constructable::getNumConstructorCalls(); 329 EXPECT_TRUE(Ctors == 2 || Ctors == 4); 330 size_t MoveCtors = Constructable::getNumMoveConstructorCalls(); 331 EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2); 332 size_t Dtors = Constructable::getNumDestructorCalls(); 333 EXPECT_TRUE(Dtors == 0 || Dtors == 2); 334 } 335 336 // Resize with fill value. 337 TYPED_TEST(SmallVectorTest, ResizeFillTest) { 338 SCOPED_TRACE("ResizeFillTest"); 339 340 this->theVector.resize(3, Constructable(77)); 341 this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77); 342 } 343 344 TEST(SmallVectorTest, ResizeForOverwrite) { 345 { 346 // Heap allocated storage. 347 SmallVector<unsigned, 0> V; 348 V.push_back(5); 349 V.pop_back(); 350 V.resize_for_overwrite(V.size() + 1); 351 EXPECT_EQ(5, V.back()); 352 V.pop_back(); 353 V.resize(V.size() + 1); 354 EXPECT_EQ(0, V.back()); 355 } 356 { 357 // Inline storage. 358 SmallVector<unsigned, 2> V; 359 V.push_back(5); 360 V.pop_back(); 361 V.resize_for_overwrite(V.size() + 1); 362 EXPECT_EQ(5, V.back()); 363 V.pop_back(); 364 V.resize(V.size() + 1); 365 EXPECT_EQ(0, V.back()); 366 } 367 } 368 369 // Overflow past fixed size. 370 TYPED_TEST(SmallVectorTest, OverflowTest) { 371 SCOPED_TRACE("OverflowTest"); 372 373 // Push more elements than the fixed size. 374 this->makeSequence(this->theVector, 1, 10); 375 376 // Test size and values. 377 EXPECT_EQ(10u, this->theVector.size()); 378 for (int i = 0; i < 10; ++i) { 379 EXPECT_EQ(i+1, this->theVector[i].getValue()); 380 } 381 382 // Now resize back to fixed size. 383 this->theVector.resize(1); 384 385 this->assertValuesInOrder(this->theVector, 1u, 1); 386 } 387 388 // Iteration tests. 389 TYPED_TEST(SmallVectorTest, IterationTest) { 390 this->makeSequence(this->theVector, 1, 2); 391 392 // Forward Iteration 393 typename TypeParam::iterator it = this->theVector.begin(); 394 EXPECT_TRUE(*it == this->theVector.front()); 395 EXPECT_TRUE(*it == this->theVector[0]); 396 EXPECT_EQ(1, it->getValue()); 397 ++it; 398 EXPECT_TRUE(*it == this->theVector[1]); 399 EXPECT_TRUE(*it == this->theVector.back()); 400 EXPECT_EQ(2, it->getValue()); 401 ++it; 402 EXPECT_TRUE(it == this->theVector.end()); 403 --it; 404 EXPECT_TRUE(*it == this->theVector[1]); 405 EXPECT_EQ(2, it->getValue()); 406 --it; 407 EXPECT_TRUE(*it == this->theVector[0]); 408 EXPECT_EQ(1, it->getValue()); 409 410 // Reverse Iteration 411 typename TypeParam::reverse_iterator rit = this->theVector.rbegin(); 412 EXPECT_TRUE(*rit == this->theVector[1]); 413 EXPECT_EQ(2, rit->getValue()); 414 ++rit; 415 EXPECT_TRUE(*rit == this->theVector[0]); 416 EXPECT_EQ(1, rit->getValue()); 417 ++rit; 418 EXPECT_TRUE(rit == this->theVector.rend()); 419 --rit; 420 EXPECT_TRUE(*rit == this->theVector[0]); 421 EXPECT_EQ(1, rit->getValue()); 422 --rit; 423 EXPECT_TRUE(*rit == this->theVector[1]); 424 EXPECT_EQ(2, rit->getValue()); 425 } 426 427 // Swap test. 428 TYPED_TEST(SmallVectorTest, SwapTest) { 429 SCOPED_TRACE("SwapTest"); 430 431 this->makeSequence(this->theVector, 1, 2); 432 std::swap(this->theVector, this->otherVector); 433 434 this->assertEmpty(this->theVector); 435 this->assertValuesInOrder(this->otherVector, 2u, 1, 2); 436 } 437 438 // Append test 439 TYPED_TEST(SmallVectorTest, AppendTest) { 440 SCOPED_TRACE("AppendTest"); 441 442 this->makeSequence(this->otherVector, 2, 3); 443 444 this->theVector.push_back(Constructable(1)); 445 this->theVector.append(this->otherVector.begin(), this->otherVector.end()); 446 447 this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); 448 } 449 450 // Append repeated test 451 TYPED_TEST(SmallVectorTest, AppendRepeatedTest) { 452 SCOPED_TRACE("AppendRepeatedTest"); 453 454 this->theVector.push_back(Constructable(1)); 455 this->theVector.append(2, Constructable(77)); 456 this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77); 457 } 458 459 // Append test 460 TYPED_TEST(SmallVectorTest, AppendNonIterTest) { 461 SCOPED_TRACE("AppendRepeatedTest"); 462 463 this->theVector.push_back(Constructable(1)); 464 this->theVector.append(2, 7); 465 this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7); 466 } 467 468 struct output_iterator { 469 typedef std::output_iterator_tag iterator_category; 470 typedef int value_type; 471 typedef int difference_type; 472 typedef value_type *pointer; 473 typedef value_type &reference; 474 operator int() { return 2; } 475 operator Constructable() { return 7; } 476 }; 477 478 TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) { 479 SCOPED_TRACE("AppendRepeatedTest"); 480 481 this->theVector.push_back(Constructable(1)); 482 this->theVector.append(output_iterator(), output_iterator()); 483 this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7); 484 } 485 486 // Assign test 487 TYPED_TEST(SmallVectorTest, AssignTest) { 488 SCOPED_TRACE("AssignTest"); 489 490 this->theVector.push_back(Constructable(1)); 491 this->theVector.assign(2, Constructable(77)); 492 this->assertValuesInOrder(this->theVector, 2u, 77, 77); 493 } 494 495 // Assign test 496 TYPED_TEST(SmallVectorTest, AssignRangeTest) { 497 SCOPED_TRACE("AssignTest"); 498 499 this->theVector.push_back(Constructable(1)); 500 int arr[] = {1, 2, 3}; 501 this->theVector.assign(std::begin(arr), std::end(arr)); 502 this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); 503 } 504 505 // Assign test 506 TYPED_TEST(SmallVectorTest, AssignNonIterTest) { 507 SCOPED_TRACE("AssignTest"); 508 509 this->theVector.push_back(Constructable(1)); 510 this->theVector.assign(2, 7); 511 this->assertValuesInOrder(this->theVector, 2u, 7, 7); 512 } 513 514 // Move-assign test 515 TYPED_TEST(SmallVectorTest, MoveAssignTest) { 516 SCOPED_TRACE("MoveAssignTest"); 517 518 // Set up our vector with a single element, but enough capacity for 4. 519 this->theVector.reserve(4); 520 this->theVector.push_back(Constructable(1)); 521 522 // Set up the other vector with 2 elements. 523 this->otherVector.push_back(Constructable(2)); 524 this->otherVector.push_back(Constructable(3)); 525 526 // Move-assign from the other vector. 527 this->theVector = std::move(this->otherVector); 528 529 // Make sure we have the right result. 530 this->assertValuesInOrder(this->theVector, 2u, 2, 3); 531 532 // Make sure the # of constructor/destructor calls line up. There 533 // are two live objects after clearing the other vector. 534 this->otherVector.clear(); 535 EXPECT_EQ(Constructable::getNumConstructorCalls()-2, 536 Constructable::getNumDestructorCalls()); 537 538 // There shouldn't be any live objects any more. 539 this->theVector.clear(); 540 EXPECT_EQ(Constructable::getNumConstructorCalls(), 541 Constructable::getNumDestructorCalls()); 542 } 543 544 // Erase a single element 545 TYPED_TEST(SmallVectorTest, EraseTest) { 546 SCOPED_TRACE("EraseTest"); 547 548 this->makeSequence(this->theVector, 1, 3); 549 const auto &theConstVector = this->theVector; 550 this->theVector.erase(theConstVector.begin()); 551 this->assertValuesInOrder(this->theVector, 2u, 2, 3); 552 } 553 554 // Erase a range of elements 555 TYPED_TEST(SmallVectorTest, EraseRangeTest) { 556 SCOPED_TRACE("EraseRangeTest"); 557 558 this->makeSequence(this->theVector, 1, 3); 559 const auto &theConstVector = this->theVector; 560 this->theVector.erase(theConstVector.begin(), theConstVector.begin() + 2); 561 this->assertValuesInOrder(this->theVector, 1u, 3); 562 } 563 564 // Insert a single element. 565 TYPED_TEST(SmallVectorTest, InsertTest) { 566 SCOPED_TRACE("InsertTest"); 567 568 this->makeSequence(this->theVector, 1, 3); 569 typename TypeParam::iterator I = 570 this->theVector.insert(this->theVector.begin() + 1, Constructable(77)); 571 EXPECT_EQ(this->theVector.begin() + 1, I); 572 this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); 573 } 574 575 // Insert a copy of a single element. 576 TYPED_TEST(SmallVectorTest, InsertCopy) { 577 SCOPED_TRACE("InsertTest"); 578 579 this->makeSequence(this->theVector, 1, 3); 580 Constructable C(77); 581 typename TypeParam::iterator I = 582 this->theVector.insert(this->theVector.begin() + 1, C); 583 EXPECT_EQ(this->theVector.begin() + 1, I); 584 this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); 585 } 586 587 // Insert repeated elements. 588 TYPED_TEST(SmallVectorTest, InsertRepeatedTest) { 589 SCOPED_TRACE("InsertRepeatedTest"); 590 591 this->makeSequence(this->theVector, 1, 4); 592 Constructable::reset(); 593 auto I = 594 this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16)); 595 // Move construct the top element into newly allocated space, and optionally 596 // reallocate the whole buffer, move constructing into it. 597 // FIXME: This is inefficient, we shouldn't move things into newly allocated 598 // space, then move them up/around, there should only be 2 or 4 move 599 // constructions here. 600 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || 601 Constructable::getNumMoveConstructorCalls() == 6); 602 // Move assign the next two to shift them up and make a gap. 603 EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls()); 604 // Copy construct the two new elements from the parameter. 605 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); 606 // All without any copy construction. 607 EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls()); 608 EXPECT_EQ(this->theVector.begin() + 1, I); 609 this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4); 610 } 611 612 TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) { 613 SCOPED_TRACE("InsertRepeatedTest"); 614 615 this->makeSequence(this->theVector, 1, 4); 616 Constructable::reset(); 617 auto I = this->theVector.insert(this->theVector.begin() + 1, 2, 7); 618 EXPECT_EQ(this->theVector.begin() + 1, I); 619 this->assertValuesInOrder(this->theVector, 6u, 1, 7, 7, 2, 3, 4); 620 } 621 622 TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) { 623 SCOPED_TRACE("InsertRepeatedTest"); 624 625 this->makeSequence(this->theVector, 1, 4); 626 Constructable::reset(); 627 auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16)); 628 // Just copy construct them into newly allocated space 629 EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls()); 630 // Move everything across if reallocation is needed. 631 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || 632 Constructable::getNumMoveConstructorCalls() == 4); 633 // Without ever moving or copying anything else. 634 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); 635 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); 636 637 EXPECT_EQ(this->theVector.begin() + 4, I); 638 this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16); 639 } 640 641 TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) { 642 SCOPED_TRACE("InsertRepeatedTest"); 643 644 this->makeSequence(this->theVector, 10, 15); 645 646 // Empty insert. 647 EXPECT_EQ(this->theVector.end(), 648 this->theVector.insert(this->theVector.end(), 649 0, Constructable(42))); 650 EXPECT_EQ(this->theVector.begin() + 1, 651 this->theVector.insert(this->theVector.begin() + 1, 652 0, Constructable(42))); 653 } 654 655 // Insert range. 656 TYPED_TEST(SmallVectorTest, InsertRangeTest) { 657 SCOPED_TRACE("InsertRangeTest"); 658 659 Constructable Arr[3] = 660 { Constructable(77), Constructable(77), Constructable(77) }; 661 662 this->makeSequence(this->theVector, 1, 3); 663 Constructable::reset(); 664 auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3); 665 // Move construct the top 3 elements into newly allocated space. 666 // Possibly move the whole sequence into new space first. 667 // FIXME: This is inefficient, we shouldn't move things into newly allocated 668 // space, then move them up/around, there should only be 2 or 3 move 669 // constructions here. 670 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || 671 Constructable::getNumMoveConstructorCalls() == 5); 672 // Copy assign the lower 2 new elements into existing space. 673 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); 674 // Copy construct the third element into newly allocated space. 675 EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls()); 676 EXPECT_EQ(this->theVector.begin() + 1, I); 677 this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3); 678 } 679 680 681 TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) { 682 SCOPED_TRACE("InsertRangeTest"); 683 684 Constructable Arr[3] = 685 { Constructable(77), Constructable(77), Constructable(77) }; 686 687 this->makeSequence(this->theVector, 1, 3); 688 689 // Insert at end. 690 Constructable::reset(); 691 auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3); 692 // Copy construct the 3 elements into new space at the top. 693 EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls()); 694 // Don't copy/move anything else. 695 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); 696 // Reallocation might occur, causing all elements to be moved into the new 697 // buffer. 698 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || 699 Constructable::getNumMoveConstructorCalls() == 3); 700 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); 701 EXPECT_EQ(this->theVector.begin() + 3, I); 702 this->assertValuesInOrder(this->theVector, 6u, 703 1, 2, 3, 77, 77, 77); 704 } 705 706 TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) { 707 SCOPED_TRACE("InsertRangeTest"); 708 709 this->makeSequence(this->theVector, 1, 3); 710 711 // Empty insert. 712 EXPECT_EQ(this->theVector.end(), 713 this->theVector.insert(this->theVector.end(), 714 this->theVector.begin(), 715 this->theVector.begin())); 716 EXPECT_EQ(this->theVector.begin() + 1, 717 this->theVector.insert(this->theVector.begin() + 1, 718 this->theVector.begin(), 719 this->theVector.begin())); 720 } 721 722 // Comparison tests. 723 TYPED_TEST(SmallVectorTest, ComparisonTest) { 724 SCOPED_TRACE("ComparisonTest"); 725 726 this->makeSequence(this->theVector, 1, 3); 727 this->makeSequence(this->otherVector, 1, 3); 728 729 EXPECT_TRUE(this->theVector == this->otherVector); 730 EXPECT_FALSE(this->theVector != this->otherVector); 731 732 this->otherVector.clear(); 733 this->makeSequence(this->otherVector, 2, 4); 734 735 EXPECT_FALSE(this->theVector == this->otherVector); 736 EXPECT_TRUE(this->theVector != this->otherVector); 737 } 738 739 // Constant vector tests. 740 TYPED_TEST(SmallVectorTest, ConstVectorTest) { 741 const TypeParam constVector; 742 743 EXPECT_EQ(0u, constVector.size()); 744 EXPECT_TRUE(constVector.empty()); 745 EXPECT_TRUE(constVector.begin() == constVector.end()); 746 } 747 748 // Direct array access. 749 TYPED_TEST(SmallVectorTest, DirectVectorTest) { 750 EXPECT_EQ(0u, this->theVector.size()); 751 this->theVector.reserve(4); 752 EXPECT_LE(4u, this->theVector.capacity()); 753 EXPECT_EQ(0, Constructable::getNumConstructorCalls()); 754 this->theVector.push_back(1); 755 this->theVector.push_back(2); 756 this->theVector.push_back(3); 757 this->theVector.push_back(4); 758 EXPECT_EQ(4u, this->theVector.size()); 759 EXPECT_EQ(8, Constructable::getNumConstructorCalls()); 760 EXPECT_EQ(1, this->theVector[0].getValue()); 761 EXPECT_EQ(2, this->theVector[1].getValue()); 762 EXPECT_EQ(3, this->theVector[2].getValue()); 763 EXPECT_EQ(4, this->theVector[3].getValue()); 764 } 765 766 TYPED_TEST(SmallVectorTest, IteratorTest) { 767 std::list<int> L; 768 this->theVector.insert(this->theVector.end(), L.begin(), L.end()); 769 } 770 771 template <typename InvalidType> class DualSmallVectorsTest; 772 773 template <typename VectorT1, typename VectorT2> 774 class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase { 775 protected: 776 VectorT1 theVector; 777 VectorT2 otherVector; 778 779 template <typename T, unsigned N> 780 static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; } 781 }; 782 783 typedef ::testing::Types< 784 // Small mode -> Small mode. 785 std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>, 786 // Small mode -> Big mode. 787 std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>, 788 // Big mode -> Small mode. 789 std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>, 790 // Big mode -> Big mode. 791 std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>> 792 > DualSmallVectorTestTypes; 793 794 TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes); 795 796 TYPED_TEST(DualSmallVectorsTest, MoveAssignment) { 797 SCOPED_TRACE("MoveAssignTest-DualVectorTypes"); 798 799 // Set up our vector with four elements. 800 for (unsigned I = 0; I < 4; ++I) 801 this->otherVector.push_back(Constructable(I)); 802 803 const Constructable *OrigDataPtr = this->otherVector.data(); 804 805 // Move-assign from the other vector. 806 this->theVector = 807 std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector)); 808 809 // Make sure we have the right result. 810 this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3); 811 812 // Make sure the # of constructor/destructor calls line up. There 813 // are two live objects after clearing the other vector. 814 this->otherVector.clear(); 815 EXPECT_EQ(Constructable::getNumConstructorCalls()-4, 816 Constructable::getNumDestructorCalls()); 817 818 // If the source vector (otherVector) was in small-mode, assert that we just 819 // moved the data pointer over. 820 EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 || 821 this->theVector.data() == OrigDataPtr); 822 823 // There shouldn't be any live objects any more. 824 this->theVector.clear(); 825 EXPECT_EQ(Constructable::getNumConstructorCalls(), 826 Constructable::getNumDestructorCalls()); 827 828 // We shouldn't have copied anything in this whole process. 829 EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0); 830 } 831 832 struct notassignable { 833 int &x; 834 notassignable(int &x) : x(x) {} 835 }; 836 837 TEST(SmallVectorCustomTest, NoAssignTest) { 838 int x = 0; 839 SmallVector<notassignable, 2> vec; 840 vec.push_back(notassignable(x)); 841 x = 42; 842 EXPECT_EQ(42, vec.pop_back_val().x); 843 } 844 845 struct MovedFrom { 846 bool hasValue; 847 MovedFrom() : hasValue(true) { 848 } 849 MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) { 850 m.hasValue = false; 851 } 852 MovedFrom &operator=(MovedFrom&& m) { 853 hasValue = m.hasValue; 854 m.hasValue = false; 855 return *this; 856 } 857 }; 858 859 TEST(SmallVectorTest, MidInsert) { 860 SmallVector<MovedFrom, 3> v; 861 v.push_back(MovedFrom()); 862 v.insert(v.begin(), MovedFrom()); 863 for (MovedFrom &m : v) 864 EXPECT_TRUE(m.hasValue); 865 } 866 867 enum EmplaceableArgState { 868 EAS_Defaulted, 869 EAS_Arg, 870 EAS_LValue, 871 EAS_RValue, 872 EAS_Failure 873 }; 874 template <int I> struct EmplaceableArg { 875 EmplaceableArgState State; 876 EmplaceableArg() : State(EAS_Defaulted) {} 877 EmplaceableArg(EmplaceableArg &&X) 878 : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {} 879 EmplaceableArg(EmplaceableArg &X) 880 : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {} 881 882 explicit EmplaceableArg(bool) : State(EAS_Arg) {} 883 884 private: 885 EmplaceableArg &operator=(EmplaceableArg &&) = delete; 886 EmplaceableArg &operator=(const EmplaceableArg &) = delete; 887 }; 888 889 enum EmplaceableState { ES_Emplaced, ES_Moved }; 890 struct Emplaceable { 891 EmplaceableArg<0> A0; 892 EmplaceableArg<1> A1; 893 EmplaceableArg<2> A2; 894 EmplaceableArg<3> A3; 895 EmplaceableState State; 896 897 Emplaceable() : State(ES_Emplaced) {} 898 899 template <class A0Ty> 900 explicit Emplaceable(A0Ty &&A0) 901 : A0(std::forward<A0Ty>(A0)), State(ES_Emplaced) {} 902 903 template <class A0Ty, class A1Ty> 904 Emplaceable(A0Ty &&A0, A1Ty &&A1) 905 : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), 906 State(ES_Emplaced) {} 907 908 template <class A0Ty, class A1Ty, class A2Ty> 909 Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2) 910 : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), 911 A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {} 912 913 template <class A0Ty, class A1Ty, class A2Ty, class A3Ty> 914 Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3) 915 : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), 916 A2(std::forward<A2Ty>(A2)), A3(std::forward<A3Ty>(A3)), 917 State(ES_Emplaced) {} 918 919 Emplaceable(Emplaceable &&) : State(ES_Moved) {} 920 Emplaceable &operator=(Emplaceable &&) { 921 State = ES_Moved; 922 return *this; 923 } 924 925 private: 926 Emplaceable(const Emplaceable &) = delete; 927 Emplaceable &operator=(const Emplaceable &) = delete; 928 }; 929 930 TEST(SmallVectorTest, EmplaceBack) { 931 EmplaceableArg<0> A0(true); 932 EmplaceableArg<1> A1(true); 933 EmplaceableArg<2> A2(true); 934 EmplaceableArg<3> A3(true); 935 { 936 SmallVector<Emplaceable, 3> V; 937 Emplaceable &back = V.emplace_back(); 938 EXPECT_TRUE(&back == &V.back()); 939 EXPECT_TRUE(V.size() == 1); 940 EXPECT_TRUE(back.State == ES_Emplaced); 941 EXPECT_TRUE(back.A0.State == EAS_Defaulted); 942 EXPECT_TRUE(back.A1.State == EAS_Defaulted); 943 EXPECT_TRUE(back.A2.State == EAS_Defaulted); 944 EXPECT_TRUE(back.A3.State == EAS_Defaulted); 945 } 946 { 947 SmallVector<Emplaceable, 3> V; 948 Emplaceable &back = V.emplace_back(std::move(A0)); 949 EXPECT_TRUE(&back == &V.back()); 950 EXPECT_TRUE(V.size() == 1); 951 EXPECT_TRUE(back.State == ES_Emplaced); 952 EXPECT_TRUE(back.A0.State == EAS_RValue); 953 EXPECT_TRUE(back.A1.State == EAS_Defaulted); 954 EXPECT_TRUE(back.A2.State == EAS_Defaulted); 955 EXPECT_TRUE(back.A3.State == EAS_Defaulted); 956 } 957 { 958 SmallVector<Emplaceable, 3> V; 959 Emplaceable &back = V.emplace_back(A0); 960 EXPECT_TRUE(&back == &V.back()); 961 EXPECT_TRUE(V.size() == 1); 962 EXPECT_TRUE(back.State == ES_Emplaced); 963 EXPECT_TRUE(back.A0.State == EAS_LValue); 964 EXPECT_TRUE(back.A1.State == EAS_Defaulted); 965 EXPECT_TRUE(back.A2.State == EAS_Defaulted); 966 EXPECT_TRUE(back.A3.State == EAS_Defaulted); 967 } 968 { 969 SmallVector<Emplaceable, 3> V; 970 Emplaceable &back = V.emplace_back(A0, A1); 971 EXPECT_TRUE(&back == &V.back()); 972 EXPECT_TRUE(V.size() == 1); 973 EXPECT_TRUE(back.State == ES_Emplaced); 974 EXPECT_TRUE(back.A0.State == EAS_LValue); 975 EXPECT_TRUE(back.A1.State == EAS_LValue); 976 EXPECT_TRUE(back.A2.State == EAS_Defaulted); 977 EXPECT_TRUE(back.A3.State == EAS_Defaulted); 978 } 979 { 980 SmallVector<Emplaceable, 3> V; 981 Emplaceable &back = V.emplace_back(std::move(A0), std::move(A1)); 982 EXPECT_TRUE(&back == &V.back()); 983 EXPECT_TRUE(V.size() == 1); 984 EXPECT_TRUE(back.State == ES_Emplaced); 985 EXPECT_TRUE(back.A0.State == EAS_RValue); 986 EXPECT_TRUE(back.A1.State == EAS_RValue); 987 EXPECT_TRUE(back.A2.State == EAS_Defaulted); 988 EXPECT_TRUE(back.A3.State == EAS_Defaulted); 989 } 990 { 991 SmallVector<Emplaceable, 3> V; 992 Emplaceable &back = V.emplace_back(std::move(A0), A1, std::move(A2), A3); 993 EXPECT_TRUE(&back == &V.back()); 994 EXPECT_TRUE(V.size() == 1); 995 EXPECT_TRUE(back.State == ES_Emplaced); 996 EXPECT_TRUE(back.A0.State == EAS_RValue); 997 EXPECT_TRUE(back.A1.State == EAS_LValue); 998 EXPECT_TRUE(back.A2.State == EAS_RValue); 999 EXPECT_TRUE(back.A3.State == EAS_LValue); 1000 } 1001 { 1002 SmallVector<int, 1> V; 1003 V.emplace_back(); 1004 V.emplace_back(42); 1005 EXPECT_EQ(2U, V.size()); 1006 EXPECT_EQ(0, V[0]); 1007 EXPECT_EQ(42, V[1]); 1008 } 1009 } 1010 1011 TEST(SmallVectorTest, DefaultInlinedElements) { 1012 SmallVector<int> V; 1013 EXPECT_TRUE(V.empty()); 1014 V.push_back(7); 1015 EXPECT_EQ(V[0], 7); 1016 1017 // Check that at least a couple layers of nested SmallVector<T>'s are allowed 1018 // by the default inline elements policy. This pattern happens in practice 1019 // with some frequency, and it seems fairly harmless even though each layer of 1020 // SmallVector's will grow the total sizeof by a vector header beyond the 1021 // "preferred" maximum sizeof. 1022 SmallVector<SmallVector<SmallVector<int>>> NestedV; 1023 NestedV.emplace_back().emplace_back().emplace_back(42); 1024 EXPECT_EQ(NestedV[0][0][0], 42); 1025 } 1026 1027 TEST(SmallVectorTest, InitializerList) { 1028 SmallVector<int, 2> V1 = {}; 1029 EXPECT_TRUE(V1.empty()); 1030 V1 = {0, 0}; 1031 EXPECT_TRUE(makeArrayRef(V1).equals({0, 0})); 1032 V1 = {-1, -1}; 1033 EXPECT_TRUE(makeArrayRef(V1).equals({-1, -1})); 1034 1035 SmallVector<int, 2> V2 = {1, 2, 3, 4}; 1036 EXPECT_TRUE(makeArrayRef(V2).equals({1, 2, 3, 4})); 1037 V2.assign({4}); 1038 EXPECT_TRUE(makeArrayRef(V2).equals({4})); 1039 V2.append({3, 2}); 1040 EXPECT_TRUE(makeArrayRef(V2).equals({4, 3, 2})); 1041 V2.insert(V2.begin() + 1, 5); 1042 EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2})); 1043 } 1044 1045 template <class VectorT> 1046 class SmallVectorReferenceInvalidationTest : public SmallVectorTestBase { 1047 protected: 1048 const char *AssertionMessage = 1049 "Attempting to reference an element of the vector in an operation \" " 1050 "\"that invalidates it"; 1051 1052 VectorT V; 1053 1054 template <typename T, unsigned N> 1055 static unsigned NumBuiltinElts(const SmallVector<T, N> &) { 1056 return N; 1057 } 1058 1059 void SetUp() override { 1060 SmallVectorTestBase::SetUp(); 1061 1062 // Fill up the small size so that insertions move the elements. 1063 V.append({0, 0, 0}); 1064 } 1065 }; 1066 1067 // Test one type that's trivially copyable (int) and one that isn't 1068 // (Constructable) since reference invalidation may be fixed differently for 1069 // each. 1070 using SmallVectorReferenceInvalidationTestTypes = 1071 ::testing::Types<SmallVector<int, 3>, SmallVector<Constructable, 3>>; 1072 1073 TYPED_TEST_CASE(SmallVectorReferenceInvalidationTest, 1074 SmallVectorReferenceInvalidationTestTypes); 1075 1076 TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBack) { 1077 auto &V = this->V; 1078 (void)V; 1079 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1080 EXPECT_DEATH(V.push_back(V.back()), this->AssertionMessage); 1081 #endif 1082 } 1083 1084 TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBackMoved) { 1085 auto &V = this->V; 1086 (void)V; 1087 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1088 EXPECT_DEATH(V.push_back(std::move(V.back())), this->AssertionMessage); 1089 #endif 1090 } 1091 1092 TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) { 1093 auto &V = this->V; 1094 (void)V; 1095 int N = this->NumBuiltinElts(V); 1096 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1097 EXPECT_DEATH(V.resize(N + 1, V.back()), this->AssertionMessage); 1098 #endif 1099 1100 // No assertion when shrinking, since the parameter isn't accessed. 1101 V.resize(N - 1, V.back()); 1102 } 1103 1104 TYPED_TEST(SmallVectorReferenceInvalidationTest, Append) { 1105 auto &V = this->V; 1106 (void)V; 1107 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1108 EXPECT_DEATH(V.append(1, V.back()), this->AssertionMessage); 1109 #endif 1110 } 1111 1112 TYPED_TEST(SmallVectorReferenceInvalidationTest, AppendRange) { 1113 auto &V = this->V; 1114 (void)V; 1115 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1116 EXPECT_DEATH(V.append(V.begin(), V.begin() + 1), this->AssertionMessage); 1117 1118 ASSERT_EQ(3u, this->NumBuiltinElts(V)); 1119 ASSERT_EQ(3u, V.size()); 1120 V.pop_back(); 1121 ASSERT_EQ(2u, V.size()); 1122 1123 // Confirm this checks for growth when there's more than one element 1124 // appended. 1125 EXPECT_DEATH(V.append(V.begin(), V.end()), this->AssertionMessage); 1126 #endif 1127 } 1128 1129 TYPED_TEST(SmallVectorReferenceInvalidationTest, Assign) { 1130 auto &V = this->V; 1131 (void)V; 1132 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1133 // Regardless of capacity, assign should never reference an internal element. 1134 EXPECT_DEATH(V.assign(1, V.back()), this->AssertionMessage); 1135 EXPECT_DEATH(V.assign(this->NumBuiltinElts(V), V.back()), 1136 this->AssertionMessage); 1137 EXPECT_DEATH(V.assign(this->NumBuiltinElts(V) + 1, V.back()), 1138 this->AssertionMessage); 1139 #endif 1140 } 1141 1142 TYPED_TEST(SmallVectorReferenceInvalidationTest, AssignRange) { 1143 auto &V = this->V; 1144 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1145 EXPECT_DEATH(V.assign(V.begin(), V.end()), this->AssertionMessage); 1146 EXPECT_DEATH(V.assign(V.begin(), V.end() - 1), this->AssertionMessage); 1147 #endif 1148 V.assign(V.begin(), V.begin()); 1149 EXPECT_TRUE(V.empty()); 1150 } 1151 1152 TYPED_TEST(SmallVectorReferenceInvalidationTest, Insert) { 1153 auto &V = this->V; 1154 (void)V; 1155 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1156 EXPECT_DEATH(V.insert(V.begin(), V.back()), this->AssertionMessage); 1157 #endif 1158 } 1159 1160 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertMoved) { 1161 auto &V = this->V; 1162 (void)V; 1163 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1164 EXPECT_DEATH(V.insert(V.begin(), std::move(V.back())), 1165 this->AssertionMessage); 1166 #endif 1167 } 1168 1169 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertN) { 1170 auto &V = this->V; 1171 (void)V; 1172 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1173 EXPECT_DEATH(V.insert(V.begin(), 2, V.back()), this->AssertionMessage); 1174 #endif 1175 } 1176 1177 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertRange) { 1178 auto &V = this->V; 1179 (void)V; 1180 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1181 EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.begin() + 1), 1182 this->AssertionMessage); 1183 1184 ASSERT_EQ(3u, this->NumBuiltinElts(V)); 1185 ASSERT_EQ(3u, V.size()); 1186 V.pop_back(); 1187 ASSERT_EQ(2u, V.size()); 1188 1189 // Confirm this checks for growth when there's more than one element 1190 // inserted. 1191 EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.end()), this->AssertionMessage); 1192 #endif 1193 } 1194 1195 TYPED_TEST(SmallVectorReferenceInvalidationTest, EmplaceBack) { 1196 auto &V = this->V; 1197 (void)V; 1198 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1199 EXPECT_DEATH(V.emplace_back(V.back()), this->AssertionMessage); 1200 #endif 1201 } 1202 1203 template <class VectorT> 1204 class SmallVectorInternalReferenceInvalidationTest 1205 : public SmallVectorTestBase { 1206 protected: 1207 const char *AssertionMessage = 1208 "Attempting to reference an element of the vector in an operation \" " 1209 "\"that invalidates it"; 1210 1211 VectorT V; 1212 1213 template <typename T, unsigned N> 1214 static unsigned NumBuiltinElts(const SmallVector<T, N> &) { 1215 return N; 1216 } 1217 1218 void SetUp() override { 1219 SmallVectorTestBase::SetUp(); 1220 1221 // Fill up the small size so that insertions move the elements. 1222 V.push_back(std::make_pair(0, 0)); 1223 } 1224 }; 1225 1226 // Test pairs of the same types from SmallVectorReferenceInvalidationTestTypes. 1227 using SmallVectorInternalReferenceInvalidationTestTypes = 1228 ::testing::Types<SmallVector<std::pair<int, int>, 1>, 1229 SmallVector<std::pair<Constructable, Constructable>, 1>>; 1230 1231 TYPED_TEST_CASE(SmallVectorInternalReferenceInvalidationTest, 1232 SmallVectorInternalReferenceInvalidationTestTypes); 1233 1234 TYPED_TEST(SmallVectorInternalReferenceInvalidationTest, EmplaceBack) { 1235 auto &V = this->V; 1236 (void)V; 1237 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST 1238 EXPECT_DEATH(V.emplace_back(V.back().first, 0), this->AssertionMessage); 1239 EXPECT_DEATH(V.emplace_back(0, V.back().second), this->AssertionMessage); 1240 #endif 1241 } 1242 1243 } // end namespace 1244