1 //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // SmallVector unit tests.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ADT/SmallVector.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/Support/Compiler.h"
16 #include "gtest/gtest.h"
24 /// A helper class that counts the total number of constructor and
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
;
40 Constructable() : constructed(true), value(0) {
41 ++numConstructorCalls
;
44 Constructable(int val
) : constructed(true), value(val
) {
45 ++numConstructorCalls
;
48 Constructable(const Constructable
& src
) : constructed(true) {
50 ++numConstructorCalls
;
51 ++numCopyConstructorCalls
;
54 Constructable(Constructable
&& src
) : constructed(true) {
57 ++numConstructorCalls
;
58 ++numMoveConstructorCalls
;
62 EXPECT_TRUE(constructed
);
67 Constructable
& operator=(const Constructable
& src
) {
68 EXPECT_TRUE(constructed
);
71 ++numCopyAssignmentCalls
;
75 Constructable
& operator=(Constructable
&& src
) {
76 EXPECT_TRUE(constructed
);
80 ++numMoveAssignmentCalls
;
84 int getValue() const {
89 numConstructorCalls
= 0;
90 numMoveConstructorCalls
= 0;
91 numCopyConstructorCalls
= 0;
92 numDestructorCalls
= 0;
93 numAssignmentCalls
= 0;
94 numMoveAssignmentCalls
= 0;
95 numCopyAssignmentCalls
= 0;
98 static int getNumConstructorCalls() {
99 return numConstructorCalls
;
102 static int getNumMoveConstructorCalls() {
103 return numMoveConstructorCalls
;
106 static int getNumCopyConstructorCalls() {
107 return numCopyConstructorCalls
;
110 static int getNumDestructorCalls() {
111 return numDestructorCalls
;
114 static int getNumAssignmentCalls() {
115 return numAssignmentCalls
;
118 static int getNumMoveAssignmentCalls() {
119 return numMoveAssignmentCalls
;
122 static int getNumCopyAssignmentCalls() {
123 return numCopyAssignmentCalls
;
126 friend bool operator==(const Constructable
&c0
, const Constructable
&c1
) {
127 return c0
.getValue() == c1
.getValue();
130 friend bool LLVM_ATTRIBUTE_UNUSED
operator!=(const Constructable
&c0
,
131 const Constructable
&c1
) {
132 return c0
.getValue() != c1
.getValue();
135 friend bool operator<(const Constructable
&c0
, const Constructable
&c1
) {
136 return c0
.getValue() < c1
.getValue();
138 friend bool LLVM_ATTRIBUTE_UNUSED
operator<=(const Constructable
&c0
,
139 const Constructable
&c1
) {
140 return c0
.getValue() <= c1
.getValue();
142 friend bool LLVM_ATTRIBUTE_UNUSED
operator>(const Constructable
&c0
,
143 const Constructable
&c1
) {
144 return c0
.getValue() > c1
.getValue();
146 friend bool LLVM_ATTRIBUTE_UNUSED
operator>=(const Constructable
&c0
,
147 const Constructable
&c1
) {
148 return c0
.getValue() >= c1
.getValue();
152 int Constructable::numConstructorCalls
;
153 int Constructable::numCopyConstructorCalls
;
154 int Constructable::numMoveConstructorCalls
;
155 int Constructable::numDestructorCalls
;
156 int Constructable::numAssignmentCalls
;
157 int Constructable::numCopyAssignmentCalls
;
158 int Constructable::numMoveAssignmentCalls
;
162 NonCopyable(NonCopyable
&&) {}
163 NonCopyable
&operator=(NonCopyable
&&) { return *this; }
165 NonCopyable(const NonCopyable
&) = delete;
166 NonCopyable
&operator=(const NonCopyable
&) = delete;
169 LLVM_ATTRIBUTE_USED
void CompileTest() {
170 SmallVector
<NonCopyable
, 0> V
;
174 // Assert that v contains the specified values, in order.
175 template <typename VectorT
>
176 void assertValuesInOrder(VectorT
&v
, size_t size
, ...) {
177 EXPECT_EQ(size
, v
.size());
181 for (size_t i
= 0; i
< size
; ++i
) {
182 int value
= va_arg(ap
, int);
183 EXPECT_EQ(value
, v
[i
].getValue());
189 template <typename VectorT
> void assertEmpty(VectorT
&v
) {
191 EXPECT_EQ(0u, v
.size());
192 EXPECT_TRUE(v
.empty());
195 EXPECT_TRUE(v
.begin() == v
.end());
198 // Generate a sequence of values to initialize the vector.
199 template <typename VectorT
> void makeSequence(VectorT
&v
, int start
, int end
) {
200 for (int i
= start
; i
<= end
; ++i
) {
201 v
.push_back(Constructable(i
));
205 template <typename T
, unsigned N
>
206 constexpr static unsigned NumBuiltinElts(const SmallVector
<T
, N
> &) {
210 class SmallVectorTestBase
: public testing::Test
{
212 void SetUp() override
{ Constructable::reset(); }
215 // Test fixture class
216 template <typename VectorT
>
217 class SmallVectorTest
: public SmallVectorTestBase
{
224 typedef ::testing::Types
<SmallVector
<Constructable
, 0>,
225 SmallVector
<Constructable
, 1>,
226 SmallVector
<Constructable
, 2>,
227 SmallVector
<Constructable
, 4>,
228 SmallVector
<Constructable
, 5>
229 > SmallVectorTestTypes
;
230 TYPED_TEST_SUITE(SmallVectorTest
, SmallVectorTestTypes
, );
233 TYPED_TEST(SmallVectorTest
, ConstructorNonIterTest
) {
234 SCOPED_TRACE("ConstructorTest");
235 auto &V
= this->theVector
;
236 V
= SmallVector
<Constructable
, 2>(2, 2);
237 assertValuesInOrder(V
, 2u, 2, 2);
241 TYPED_TEST(SmallVectorTest
, ConstructorIterTest
) {
242 SCOPED_TRACE("ConstructorTest");
243 int arr
[] = {1, 2, 3};
244 auto &V
= this->theVector
;
245 V
= SmallVector
<Constructable
, 4>(std::begin(arr
), std::end(arr
));
246 assertValuesInOrder(V
, 3u, 1, 2, 3);
250 TYPED_TEST(SmallVectorTest
, ConstructorFromArrayRefSimpleTest
) {
251 SCOPED_TRACE("ConstructorFromArrayRefSimpleTest");
252 std::array
<Constructable
, 3> StdArray
= {Constructable(1), Constructable(2),
254 ArrayRef
<Constructable
> Array
= StdArray
;
255 auto &V
= this->theVector
;
256 V
= SmallVector
<Constructable
, 4>(Array
);
257 assertValuesInOrder(V
, 3u, 1, 2, 3);
258 ASSERT_EQ(NumBuiltinElts(TypeParam
{}), NumBuiltinElts(V
));
262 TYPED_TEST(SmallVectorTest
, EmptyVectorTest
) {
263 SCOPED_TRACE("EmptyVectorTest");
264 auto &V
= this->theVector
;
266 EXPECT_TRUE(V
.rbegin() == V
.rend());
267 EXPECT_EQ(0, Constructable::getNumConstructorCalls());
268 EXPECT_EQ(0, Constructable::getNumDestructorCalls());
271 // Simple insertions and deletions.
272 TYPED_TEST(SmallVectorTest
, PushPopTest
) {
273 SCOPED_TRACE("PushPopTest");
274 auto &V
= this->theVector
;
275 // Track whether the vector will potentially have to grow.
276 bool RequiresGrowth
= V
.capacity() < 3;
279 V
.push_back(Constructable(1));
282 assertValuesInOrder(V
, 1u, 1);
283 EXPECT_FALSE(V
.begin() == V
.end());
284 EXPECT_FALSE(V
.empty());
286 // Push another element
287 V
.push_back(Constructable(2));
288 assertValuesInOrder(V
, 2u, 1, 2);
290 // Insert at beginning. Reserve space to avoid reference invalidation from
292 V
.reserve(V
.size() + 1);
293 V
.insert(V
.begin(), V
[1]);
294 assertValuesInOrder(V
, 3u, 2, 1, 2);
298 assertValuesInOrder(V
, 2u, 2, 1);
300 // Pop remaining elements
304 // Check number of constructor calls. Should be 2 for each list element,
305 // one for the argument to push_back, one for the argument to insert,
306 // and one for the list element itself.
307 if (!RequiresGrowth
) {
308 EXPECT_EQ(5, Constructable::getNumConstructorCalls());
309 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
311 // If we had to grow the vector, these only have a lower bound, but should
313 EXPECT_LE(5, Constructable::getNumConstructorCalls());
314 EXPECT_EQ(Constructable::getNumConstructorCalls(),
315 Constructable::getNumDestructorCalls());
320 TYPED_TEST(SmallVectorTest
, ClearTest
) {
321 SCOPED_TRACE("ClearTest");
322 auto &V
= this->theVector
;
324 makeSequence(V
, 1, 2);
328 EXPECT_EQ(4, Constructable::getNumConstructorCalls());
329 EXPECT_EQ(4, Constructable::getNumDestructorCalls());
332 // Resize smaller test.
333 TYPED_TEST(SmallVectorTest
, ResizeShrinkTest
) {
334 SCOPED_TRACE("ResizeShrinkTest");
335 auto &V
= this->theVector
;
337 makeSequence(V
, 1, 3);
340 assertValuesInOrder(V
, 1u, 1);
341 EXPECT_EQ(6, Constructable::getNumConstructorCalls());
342 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
346 TYPED_TEST(SmallVectorTest
, TruncateTest
) {
347 SCOPED_TRACE("TruncateTest");
348 auto &V
= this->theVector
;
350 makeSequence(V
, 1, 3);
353 assertValuesInOrder(V
, 1u, 1);
354 EXPECT_EQ(6, Constructable::getNumConstructorCalls());
355 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
357 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
358 EXPECT_DEATH(V
.truncate(2), "Cannot increase size");
361 assertValuesInOrder(V
, 1u, 1);
362 EXPECT_EQ(6, Constructable::getNumConstructorCalls());
363 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
367 EXPECT_EQ(6, Constructable::getNumConstructorCalls());
368 EXPECT_EQ(6, Constructable::getNumDestructorCalls());
371 // Resize bigger test.
372 TYPED_TEST(SmallVectorTest
, ResizeGrowTest
) {
373 SCOPED_TRACE("ResizeGrowTest");
374 auto &V
= this->theVector
;
377 EXPECT_EQ(2, Constructable::getNumConstructorCalls());
378 EXPECT_EQ(0, Constructable::getNumDestructorCalls());
379 EXPECT_EQ(2u, V
.size());
382 TYPED_TEST(SmallVectorTest
, ResizeWithElementsTest
) {
383 auto &V
= this->theVector
;
386 Constructable::reset();
390 size_t Ctors
= Constructable::getNumConstructorCalls();
391 EXPECT_TRUE(Ctors
== 2 || Ctors
== 4);
392 size_t MoveCtors
= Constructable::getNumMoveConstructorCalls();
393 EXPECT_TRUE(MoveCtors
== 0 || MoveCtors
== 2);
394 size_t Dtors
= Constructable::getNumDestructorCalls();
395 EXPECT_TRUE(Dtors
== 0 || Dtors
== 2);
398 // Resize with fill value.
399 TYPED_TEST(SmallVectorTest
, ResizeFillTest
) {
400 SCOPED_TRACE("ResizeFillTest");
401 auto &V
= this->theVector
;
402 V
.resize(3, Constructable(77));
403 assertValuesInOrder(V
, 3u, 77, 77, 77);
406 TEST(SmallVectorTest
, ResizeForOverwrite
) {
408 // Heap allocated storage.
409 SmallVector
<unsigned, 0> V
;
412 V
.resize_for_overwrite(V
.size() + 1U);
413 EXPECT_EQ(5U, V
.back());
415 V
.resize(V
.size() + 1);
416 EXPECT_EQ(0U, V
.back());
420 SmallVector
<unsigned, 2> V
;
423 V
.resize_for_overwrite(V
.size() + 1U);
424 EXPECT_EQ(5U, V
.back());
426 V
.resize(V
.size() + 1);
427 EXPECT_EQ(0U, V
.back());
431 // Overflow past fixed size.
432 TYPED_TEST(SmallVectorTest
, OverflowTest
) {
433 SCOPED_TRACE("OverflowTest");
434 auto &V
= this->theVector
;
435 // Push more elements than the fixed size.
436 makeSequence(V
, 1, 10);
438 // Test size and values.
439 EXPECT_EQ(10u, V
.size());
440 for (int i
= 0; i
< 10; ++i
) {
441 EXPECT_EQ(i
+ 1, V
[i
].getValue());
444 // Now resize back to fixed size.
447 assertValuesInOrder(V
, 1u, 1);
451 TYPED_TEST(SmallVectorTest
, IterationTest
) {
452 auto &V
= this->theVector
;
453 makeSequence(V
, 1, 2);
456 typename
TypeParam::iterator it
= V
.begin();
457 EXPECT_TRUE(*it
== V
.front());
458 EXPECT_TRUE(*it
== V
[0]);
459 EXPECT_EQ(1, it
->getValue());
461 EXPECT_TRUE(*it
== V
[1]);
462 EXPECT_TRUE(*it
== V
.back());
463 EXPECT_EQ(2, it
->getValue());
465 EXPECT_TRUE(it
== V
.end());
467 EXPECT_TRUE(*it
== V
[1]);
468 EXPECT_EQ(2, it
->getValue());
470 EXPECT_TRUE(*it
== V
[0]);
471 EXPECT_EQ(1, it
->getValue());
474 typename
TypeParam::reverse_iterator rit
= V
.rbegin();
475 EXPECT_TRUE(*rit
== V
[1]);
476 EXPECT_EQ(2, rit
->getValue());
478 EXPECT_TRUE(*rit
== V
[0]);
479 EXPECT_EQ(1, rit
->getValue());
481 EXPECT_TRUE(rit
== V
.rend());
483 EXPECT_TRUE(*rit
== V
[0]);
484 EXPECT_EQ(1, rit
->getValue());
486 EXPECT_TRUE(*rit
== V
[1]);
487 EXPECT_EQ(2, rit
->getValue());
491 TYPED_TEST(SmallVectorTest
, SwapTest
) {
492 SCOPED_TRACE("SwapTest");
493 auto &V
= this->theVector
;
494 auto &U
= this->otherVector
;
495 makeSequence(V
, 1, 2);
499 assertValuesInOrder(U
, 2u, 1, 2);
503 TYPED_TEST(SmallVectorTest
, AppendTest
) {
504 SCOPED_TRACE("AppendTest");
505 auto &V
= this->theVector
;
506 auto &U
= this->otherVector
;
507 makeSequence(U
, 2, 3);
509 V
.push_back(Constructable(1));
510 V
.append(U
.begin(), U
.end());
512 assertValuesInOrder(V
, 3u, 1, 2, 3);
515 // Append repeated test
516 TYPED_TEST(SmallVectorTest
, AppendRepeatedTest
) {
517 SCOPED_TRACE("AppendRepeatedTest");
518 auto &V
= this->theVector
;
519 V
.push_back(Constructable(1));
520 V
.append(2, Constructable(77));
521 assertValuesInOrder(V
, 3u, 1, 77, 77);
525 TYPED_TEST(SmallVectorTest
, AppendNonIterTest
) {
526 SCOPED_TRACE("AppendRepeatedTest");
527 auto &V
= this->theVector
;
528 V
.push_back(Constructable(1));
530 assertValuesInOrder(V
, 3u, 1, 7, 7);
533 struct output_iterator
{
534 typedef std::output_iterator_tag iterator_category
;
535 typedef int value_type
;
536 typedef int difference_type
;
537 typedef value_type
*pointer
;
538 typedef value_type
&reference
;
539 operator int() { return 2; }
540 operator Constructable() { return 7; }
543 TYPED_TEST(SmallVectorTest
, AppendRepeatedNonForwardIterator
) {
544 SCOPED_TRACE("AppendRepeatedTest");
545 auto &V
= this->theVector
;
546 V
.push_back(Constructable(1));
547 V
.append(output_iterator(), output_iterator());
548 assertValuesInOrder(V
, 3u, 1, 7, 7);
551 TYPED_TEST(SmallVectorTest
, AppendSmallVector
) {
552 SCOPED_TRACE("AppendSmallVector");
553 auto &V
= this->theVector
;
554 SmallVector
<Constructable
, 3> otherVector
= {7, 7};
555 V
.push_back(Constructable(1));
556 V
.append(otherVector
);
557 assertValuesInOrder(V
, 3u, 1, 7, 7);
561 TYPED_TEST(SmallVectorTest
, AssignTest
) {
562 SCOPED_TRACE("AssignTest");
563 auto &V
= this->theVector
;
564 V
.push_back(Constructable(1));
565 V
.assign(2, Constructable(77));
566 assertValuesInOrder(V
, 2u, 77, 77);
570 TYPED_TEST(SmallVectorTest
, AssignRangeTest
) {
571 SCOPED_TRACE("AssignTest");
572 auto &V
= this->theVector
;
573 V
.push_back(Constructable(1));
574 int arr
[] = {1, 2, 3};
575 V
.assign(std::begin(arr
), std::end(arr
));
576 assertValuesInOrder(V
, 3u, 1, 2, 3);
580 TYPED_TEST(SmallVectorTest
, AssignNonIterTest
) {
581 SCOPED_TRACE("AssignTest");
582 auto &V
= this->theVector
;
583 V
.push_back(Constructable(1));
585 assertValuesInOrder(V
, 2u, 7, 7);
588 TYPED_TEST(SmallVectorTest
, AssignSmallVector
) {
589 SCOPED_TRACE("AssignSmallVector");
590 auto &V
= this->theVector
;
591 SmallVector
<Constructable
, 3> otherVector
= {7, 7};
592 V
.push_back(Constructable(1));
593 V
.assign(otherVector
);
594 assertValuesInOrder(V
, 2u, 7, 7);
598 TYPED_TEST(SmallVectorTest
, MoveAssignTest
) {
599 SCOPED_TRACE("MoveAssignTest");
600 auto &V
= this->theVector
;
601 auto &U
= this->otherVector
;
602 // Set up our vector with a single element, but enough capacity for 4.
604 V
.push_back(Constructable(1));
606 // Set up the other vector with 2 elements.
607 U
.push_back(Constructable(2));
608 U
.push_back(Constructable(3));
610 // Move-assign from the other vector.
613 // Make sure we have the right result.
614 assertValuesInOrder(V
, 2u, 2, 3);
616 // Make sure the # of constructor/destructor calls line up. There
617 // are two live objects after clearing the other vector.
619 EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
620 Constructable::getNumDestructorCalls());
622 // There shouldn't be any live objects any more.
624 EXPECT_EQ(Constructable::getNumConstructorCalls(),
625 Constructable::getNumDestructorCalls());
628 // Erase a single element
629 TYPED_TEST(SmallVectorTest
, EraseTest
) {
630 SCOPED_TRACE("EraseTest");
631 auto &V
= this->theVector
;
632 makeSequence(V
, 1, 3);
633 const auto &theConstVector
= V
;
634 V
.erase(theConstVector
.begin());
635 assertValuesInOrder(V
, 2u, 2, 3);
638 // Erase a range of elements
639 TYPED_TEST(SmallVectorTest
, EraseRangeTest
) {
640 SCOPED_TRACE("EraseRangeTest");
641 auto &V
= this->theVector
;
642 makeSequence(V
, 1, 3);
643 const auto &theConstVector
= V
;
644 V
.erase(theConstVector
.begin(), theConstVector
.begin() + 2);
645 assertValuesInOrder(V
, 1u, 3);
648 // Insert a single element.
649 TYPED_TEST(SmallVectorTest
, InsertTest
) {
650 SCOPED_TRACE("InsertTest");
651 auto &V
= this->theVector
;
652 makeSequence(V
, 1, 3);
653 typename
TypeParam::iterator I
= V
.insert(V
.begin() + 1, Constructable(77));
654 EXPECT_EQ(V
.begin() + 1, I
);
655 assertValuesInOrder(V
, 4u, 1, 77, 2, 3);
658 // Insert a copy of a single element.
659 TYPED_TEST(SmallVectorTest
, InsertCopy
) {
660 SCOPED_TRACE("InsertTest");
661 auto &V
= this->theVector
;
662 makeSequence(V
, 1, 3);
664 typename
TypeParam::iterator I
= V
.insert(V
.begin() + 1, C
);
665 EXPECT_EQ(V
.begin() + 1, I
);
666 assertValuesInOrder(V
, 4u, 1, 77, 2, 3);
669 // Insert repeated elements.
670 TYPED_TEST(SmallVectorTest
, InsertRepeatedTest
) {
671 SCOPED_TRACE("InsertRepeatedTest");
672 auto &V
= this->theVector
;
673 makeSequence(V
, 1, 4);
674 Constructable::reset();
675 auto I
= V
.insert(V
.begin() + 1, 2, Constructable(16));
676 // Move construct the top element into newly allocated space, and optionally
677 // reallocate the whole buffer, move constructing into it.
678 // FIXME: This is inefficient, we shouldn't move things into newly allocated
679 // space, then move them up/around, there should only be 2 or 4 move
680 // constructions here.
681 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
682 Constructable::getNumMoveConstructorCalls() == 6);
683 // Move assign the next two to shift them up and make a gap.
684 EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
685 // Copy construct the two new elements from the parameter.
686 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
687 // All without any copy construction.
688 EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
689 EXPECT_EQ(V
.begin() + 1, I
);
690 assertValuesInOrder(V
, 6u, 1, 16, 16, 2, 3, 4);
693 TYPED_TEST(SmallVectorTest
, InsertRepeatedNonIterTest
) {
694 SCOPED_TRACE("InsertRepeatedTest");
695 auto &V
= this->theVector
;
696 makeSequence(V
, 1, 4);
697 Constructable::reset();
698 auto I
= V
.insert(V
.begin() + 1, 2, 7);
699 EXPECT_EQ(V
.begin() + 1, I
);
700 assertValuesInOrder(V
, 6u, 1, 7, 7, 2, 3, 4);
703 TYPED_TEST(SmallVectorTest
, InsertRepeatedAtEndTest
) {
704 SCOPED_TRACE("InsertRepeatedTest");
705 auto &V
= this->theVector
;
706 makeSequence(V
, 1, 4);
707 Constructable::reset();
708 auto I
= V
.insert(V
.end(), 2, Constructable(16));
709 // Just copy construct them into newly allocated space
710 EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
711 // Move everything across if reallocation is needed.
712 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
713 Constructable::getNumMoveConstructorCalls() == 4);
714 // Without ever moving or copying anything else.
715 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
716 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
718 EXPECT_EQ(V
.begin() + 4, I
);
719 assertValuesInOrder(V
, 6u, 1, 2, 3, 4, 16, 16);
722 TYPED_TEST(SmallVectorTest
, InsertRepeatedEmptyTest
) {
723 SCOPED_TRACE("InsertRepeatedTest");
724 auto &V
= this->theVector
;
725 makeSequence(V
, 10, 15);
728 EXPECT_EQ(V
.end(), V
.insert(V
.end(), 0, Constructable(42)));
729 EXPECT_EQ(V
.begin() + 1, V
.insert(V
.begin() + 1, 0, Constructable(42)));
733 TYPED_TEST(SmallVectorTest
, InsertRangeTest
) {
734 SCOPED_TRACE("InsertRangeTest");
735 auto &V
= this->theVector
;
736 Constructable Arr
[3] =
737 { Constructable(77), Constructable(77), Constructable(77) };
739 makeSequence(V
, 1, 3);
740 Constructable::reset();
741 auto I
= V
.insert(V
.begin() + 1, Arr
, Arr
+ 3);
742 // Move construct the top 3 elements into newly allocated space.
743 // Possibly move the whole sequence into new space first.
744 // FIXME: This is inefficient, we shouldn't move things into newly allocated
745 // space, then move them up/around, there should only be 2 or 3 move
746 // constructions here.
747 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
748 Constructable::getNumMoveConstructorCalls() == 5);
749 // Copy assign the lower 2 new elements into existing space.
750 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
751 // Copy construct the third element into newly allocated space.
752 EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
753 EXPECT_EQ(V
.begin() + 1, I
);
754 assertValuesInOrder(V
, 6u, 1, 77, 77, 77, 2, 3);
758 TYPED_TEST(SmallVectorTest
, InsertRangeAtEndTest
) {
759 SCOPED_TRACE("InsertRangeTest");
760 auto &V
= this->theVector
;
761 Constructable Arr
[3] =
762 { Constructable(77), Constructable(77), Constructable(77) };
764 makeSequence(V
, 1, 3);
767 Constructable::reset();
768 auto I
= V
.insert(V
.end(), Arr
, Arr
+ 3);
769 // Copy construct the 3 elements into new space at the top.
770 EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
771 // Don't copy/move anything else.
772 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
773 // Reallocation might occur, causing all elements to be moved into the new
775 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
776 Constructable::getNumMoveConstructorCalls() == 3);
777 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
778 EXPECT_EQ(V
.begin() + 3, I
);
779 assertValuesInOrder(V
, 6u, 1, 2, 3, 77, 77, 77);
782 TYPED_TEST(SmallVectorTest
, InsertEmptyRangeTest
) {
783 SCOPED_TRACE("InsertRangeTest");
784 auto &V
= this->theVector
;
785 makeSequence(V
, 1, 3);
788 EXPECT_EQ(V
.end(), V
.insert(V
.end(), V
.begin(), V
.begin()));
789 EXPECT_EQ(V
.begin() + 1, V
.insert(V
.begin() + 1, V
.begin(), V
.begin()));
793 TYPED_TEST(SmallVectorTest
, ComparisonEqualityTest
) {
794 SCOPED_TRACE("ComparisonEqualityTest");
795 auto &V
= this->theVector
;
796 auto &U
= this->otherVector
;
797 makeSequence(V
, 1, 3);
798 makeSequence(U
, 1, 3);
801 EXPECT_FALSE(V
!= U
);
804 makeSequence(U
, 2, 4);
806 EXPECT_FALSE(V
== U
);
811 TYPED_TEST(SmallVectorTest
, ComparisonLessThanTest
) {
812 SCOPED_TRACE("ComparisonLessThanTest");
813 auto &V
= this->theVector
;
814 auto &U
= this->otherVector
;
821 EXPECT_FALSE(V
>= U
);
824 EXPECT_FALSE(U
<= V
);
841 // Constant vector tests.
842 TYPED_TEST(SmallVectorTest
, ConstVectorTest
) {
843 const TypeParam constVector
;
845 EXPECT_EQ(0u, constVector
.size());
846 EXPECT_TRUE(constVector
.empty());
847 EXPECT_TRUE(constVector
.begin() == constVector
.end());
850 // Direct array access.
851 TYPED_TEST(SmallVectorTest
, DirectVectorTest
) {
852 auto &V
= this->theVector
;
853 EXPECT_EQ(0u, V
.size());
855 EXPECT_LE(4u, V
.capacity());
856 EXPECT_EQ(0, Constructable::getNumConstructorCalls());
861 EXPECT_EQ(4u, V
.size());
862 EXPECT_EQ(8, Constructable::getNumConstructorCalls());
863 EXPECT_EQ(1, V
[0].getValue());
864 EXPECT_EQ(2, V
[1].getValue());
865 EXPECT_EQ(3, V
[2].getValue());
866 EXPECT_EQ(4, V
[3].getValue());
869 TYPED_TEST(SmallVectorTest
, IteratorTest
) {
870 auto &V
= this->theVector
;
872 V
.insert(V
.end(), L
.begin(), L
.end());
875 template <typename InvalidType
> class DualSmallVectorsTest
;
877 template <typename VectorT1
, typename VectorT2
>
878 class DualSmallVectorsTest
<std::pair
<VectorT1
, VectorT2
>> : public SmallVectorTestBase
{
881 VectorT2 otherVector
;
884 typedef ::testing::Types
<
885 // Small mode -> Small mode.
886 std::pair
<SmallVector
<Constructable
, 4>, SmallVector
<Constructable
, 4>>,
887 // Small mode -> Big mode.
888 std::pair
<SmallVector
<Constructable
, 4>, SmallVector
<Constructable
, 2>>,
889 // Big mode -> Small mode.
890 std::pair
<SmallVector
<Constructable
, 2>, SmallVector
<Constructable
, 4>>,
891 // Big mode -> Big mode.
892 std::pair
<SmallVector
<Constructable
, 2>, SmallVector
<Constructable
, 2>>
893 > DualSmallVectorTestTypes
;
895 TYPED_TEST_SUITE(DualSmallVectorsTest
, DualSmallVectorTestTypes
, );
897 TYPED_TEST(DualSmallVectorsTest
, MoveAssignment
) {
898 SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
899 auto &V
= this->theVector
;
900 auto &U
= this->otherVector
;
901 // Set up our vector with four elements.
902 for (unsigned I
= 0; I
< 4; ++I
)
903 U
.push_back(Constructable(I
));
905 const Constructable
*OrigDataPtr
= U
.data();
907 // Move-assign from the other vector.
908 V
= std::move(static_cast<SmallVectorImpl
<Constructable
> &>(U
));
910 // Make sure we have the right result.
911 assertValuesInOrder(V
, 4u, 0, 1, 2, 3);
913 // Make sure the # of constructor/destructor calls line up. There
914 // are two live objects after clearing the other vector.
916 EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
917 Constructable::getNumDestructorCalls());
919 // If the source vector (otherVector) was in small-mode, assert that we just
920 // moved the data pointer over.
921 EXPECT_TRUE(NumBuiltinElts(U
) == 4 || V
.data() == OrigDataPtr
);
923 // There shouldn't be any live objects any more.
925 EXPECT_EQ(Constructable::getNumConstructorCalls(),
926 Constructable::getNumDestructorCalls());
928 // We shouldn't have copied anything in this whole process.
929 EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
932 struct notassignable
{
934 notassignable(int &x
) : x(x
) {}
937 TEST(SmallVectorCustomTest
, NoAssignTest
) {
939 SmallVector
<notassignable
, 2> vec
;
940 vec
.push_back(notassignable(x
));
942 EXPECT_EQ(42, vec
.pop_back_val().x
);
947 MovedFrom() : hasValue(true) {
949 MovedFrom(MovedFrom
&& m
) : hasValue(m
.hasValue
) {
952 MovedFrom
&operator=(MovedFrom
&& m
) {
953 hasValue
= m
.hasValue
;
959 TEST(SmallVectorTest
, MidInsert
) {
960 SmallVector
<MovedFrom
, 3> v
;
961 v
.push_back(MovedFrom());
962 v
.insert(v
.begin(), MovedFrom());
963 for (MovedFrom
&m
: v
)
964 EXPECT_TRUE(m
.hasValue
);
967 enum EmplaceableArgState
{
974 template <int I
> struct EmplaceableArg
{
975 EmplaceableArgState State
;
976 EmplaceableArg() : State(EAS_Defaulted
) {}
977 EmplaceableArg(EmplaceableArg
&&X
)
978 : State(X
.State
== EAS_Arg
? EAS_RValue
: EAS_Failure
) {}
979 EmplaceableArg(EmplaceableArg
&X
)
980 : State(X
.State
== EAS_Arg
? EAS_LValue
: EAS_Failure
) {}
982 explicit EmplaceableArg(bool) : State(EAS_Arg
) {}
985 EmplaceableArg
&operator=(EmplaceableArg
&&) = delete;
986 EmplaceableArg
&operator=(const EmplaceableArg
&) = delete;
989 enum EmplaceableState
{ ES_Emplaced
, ES_Moved
};
991 EmplaceableArg
<0> A0
;
992 EmplaceableArg
<1> A1
;
993 EmplaceableArg
<2> A2
;
994 EmplaceableArg
<3> A3
;
995 EmplaceableState State
;
997 Emplaceable() : State(ES_Emplaced
) {}
999 template <class A0Ty
>
1000 explicit Emplaceable(A0Ty
&&A0
)
1001 : A0(std::forward
<A0Ty
>(A0
)), State(ES_Emplaced
) {}
1003 template <class A0Ty
, class A1Ty
>
1004 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
)
1005 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
1006 State(ES_Emplaced
) {}
1008 template <class A0Ty
, class A1Ty
, class A2Ty
>
1009 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
, A2Ty
&&A2
)
1010 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
1011 A2(std::forward
<A2Ty
>(A2
)), State(ES_Emplaced
) {}
1013 template <class A0Ty
, class A1Ty
, class A2Ty
, class A3Ty
>
1014 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
, A2Ty
&&A2
, A3Ty
&&A3
)
1015 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
1016 A2(std::forward
<A2Ty
>(A2
)), A3(std::forward
<A3Ty
>(A3
)),
1017 State(ES_Emplaced
) {}
1019 Emplaceable(Emplaceable
&&) : State(ES_Moved
) {}
1020 Emplaceable
&operator=(Emplaceable
&&) {
1026 Emplaceable(const Emplaceable
&) = delete;
1027 Emplaceable
&operator=(const Emplaceable
&) = delete;
1030 TEST(SmallVectorTest
, EmplaceBack
) {
1031 EmplaceableArg
<0> A0(true);
1032 EmplaceableArg
<1> A1(true);
1033 EmplaceableArg
<2> A2(true);
1034 EmplaceableArg
<3> A3(true);
1036 SmallVector
<Emplaceable
, 3> V
;
1037 Emplaceable
&back
= V
.emplace_back();
1038 EXPECT_TRUE(&back
== &V
.back());
1039 EXPECT_TRUE(V
.size() == 1);
1040 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1041 EXPECT_TRUE(back
.A0
.State
== EAS_Defaulted
);
1042 EXPECT_TRUE(back
.A1
.State
== EAS_Defaulted
);
1043 EXPECT_TRUE(back
.A2
.State
== EAS_Defaulted
);
1044 EXPECT_TRUE(back
.A3
.State
== EAS_Defaulted
);
1047 SmallVector
<Emplaceable
, 3> V
;
1048 Emplaceable
&back
= V
.emplace_back(std::move(A0
));
1049 EXPECT_TRUE(&back
== &V
.back());
1050 EXPECT_TRUE(V
.size() == 1);
1051 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1052 EXPECT_TRUE(back
.A0
.State
== EAS_RValue
);
1053 EXPECT_TRUE(back
.A1
.State
== EAS_Defaulted
);
1054 EXPECT_TRUE(back
.A2
.State
== EAS_Defaulted
);
1055 EXPECT_TRUE(back
.A3
.State
== EAS_Defaulted
);
1058 SmallVector
<Emplaceable
, 3> V
;
1059 Emplaceable
&back
= V
.emplace_back(A0
);
1060 EXPECT_TRUE(&back
== &V
.back());
1061 EXPECT_TRUE(V
.size() == 1);
1062 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1063 EXPECT_TRUE(back
.A0
.State
== EAS_LValue
);
1064 EXPECT_TRUE(back
.A1
.State
== EAS_Defaulted
);
1065 EXPECT_TRUE(back
.A2
.State
== EAS_Defaulted
);
1066 EXPECT_TRUE(back
.A3
.State
== EAS_Defaulted
);
1069 SmallVector
<Emplaceable
, 3> V
;
1070 Emplaceable
&back
= V
.emplace_back(A0
, A1
);
1071 EXPECT_TRUE(&back
== &V
.back());
1072 EXPECT_TRUE(V
.size() == 1);
1073 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1074 EXPECT_TRUE(back
.A0
.State
== EAS_LValue
);
1075 EXPECT_TRUE(back
.A1
.State
== EAS_LValue
);
1076 EXPECT_TRUE(back
.A2
.State
== EAS_Defaulted
);
1077 EXPECT_TRUE(back
.A3
.State
== EAS_Defaulted
);
1080 SmallVector
<Emplaceable
, 3> V
;
1081 Emplaceable
&back
= V
.emplace_back(std::move(A0
), std::move(A1
));
1082 EXPECT_TRUE(&back
== &V
.back());
1083 EXPECT_TRUE(V
.size() == 1);
1084 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1085 EXPECT_TRUE(back
.A0
.State
== EAS_RValue
);
1086 EXPECT_TRUE(back
.A1
.State
== EAS_RValue
);
1087 EXPECT_TRUE(back
.A2
.State
== EAS_Defaulted
);
1088 EXPECT_TRUE(back
.A3
.State
== EAS_Defaulted
);
1091 SmallVector
<Emplaceable
, 3> V
;
1092 Emplaceable
&back
= V
.emplace_back(std::move(A0
), A1
, std::move(A2
), A3
);
1093 EXPECT_TRUE(&back
== &V
.back());
1094 EXPECT_TRUE(V
.size() == 1);
1095 EXPECT_TRUE(back
.State
== ES_Emplaced
);
1096 EXPECT_TRUE(back
.A0
.State
== EAS_RValue
);
1097 EXPECT_TRUE(back
.A1
.State
== EAS_LValue
);
1098 EXPECT_TRUE(back
.A2
.State
== EAS_RValue
);
1099 EXPECT_TRUE(back
.A3
.State
== EAS_LValue
);
1102 SmallVector
<int, 1> V
;
1105 EXPECT_EQ(2U, V
.size());
1107 EXPECT_EQ(42, V
[1]);
1111 TEST(SmallVectorTest
, DefaultInlinedElements
) {
1113 EXPECT_TRUE(V
.empty());
1117 // Check that at least a couple layers of nested SmallVector<T>'s are allowed
1118 // by the default inline elements policy. This pattern happens in practice
1119 // with some frequency, and it seems fairly harmless even though each layer of
1120 // SmallVector's will grow the total sizeof by a vector header beyond the
1121 // "preferred" maximum sizeof.
1122 SmallVector
<SmallVector
<SmallVector
<int>>> NestedV
;
1123 NestedV
.emplace_back().emplace_back().emplace_back(42);
1124 EXPECT_EQ(NestedV
[0][0][0], 42);
1127 TEST(SmallVectorTest
, InitializerList
) {
1128 SmallVector
<int, 2> V1
= {};
1129 EXPECT_TRUE(V1
.empty());
1131 EXPECT_TRUE(makeArrayRef(V1
).equals({0, 0}));
1133 EXPECT_TRUE(makeArrayRef(V1
).equals({-1, -1}));
1135 SmallVector
<int, 2> V2
= {1, 2, 3, 4};
1136 EXPECT_TRUE(makeArrayRef(V2
).equals({1, 2, 3, 4}));
1138 EXPECT_TRUE(makeArrayRef(V2
).equals({4}));
1140 EXPECT_TRUE(makeArrayRef(V2
).equals({4, 3, 2}));
1141 V2
.insert(V2
.begin() + 1, 5);
1142 EXPECT_TRUE(makeArrayRef(V2
).equals({4, 5, 3, 2}));
1145 TEST(SmallVectorTest
, ToVector
) {
1147 std::vector
<char> v
= {'a', 'b', 'c'};
1148 auto Vector
= to_vector
<4>(v
);
1149 static_assert(NumBuiltinElts(Vector
) == 4u);
1150 ASSERT_EQ(3u, Vector
.size());
1151 for (size_t I
= 0; I
< v
.size(); ++I
)
1152 EXPECT_EQ(v
[I
], Vector
[I
]);
1155 std::vector
<char> v
= {'a', 'b', 'c'};
1156 auto Vector
= to_vector(v
);
1157 static_assert(NumBuiltinElts(Vector
) != 4u);
1158 ASSERT_EQ(3u, Vector
.size());
1159 for (size_t I
= 0; I
< v
.size(); ++I
)
1160 EXPECT_EQ(v
[I
], Vector
[I
]);
1166 friend bool operator==(const To
&LHS
, const To
&RHS
) {
1167 return LHS
.Content
== RHS
.Content
;
1174 From(To M
) { T
= M
; }
1175 operator To() const { return T
; }
1181 TEST(SmallVectorTest
, ConstructFromArrayRefOfConvertibleType
) {
1182 To to1
{1}, to2
{2}, to3
{3};
1183 std::vector
<From
> StdVector
= {From(to1
), From(to2
), From(to3
)};
1184 ArrayRef
<From
> Array
= StdVector
;
1186 llvm::SmallVector
<To
> Vector(Array
);
1188 ASSERT_EQ(Array
.size(), Vector
.size());
1189 for (size_t I
= 0; I
< Array
.size(); ++I
)
1190 EXPECT_EQ(Array
[I
], Vector
[I
]);
1193 llvm::SmallVector
<To
, 4> Vector(Array
);
1195 ASSERT_EQ(Array
.size(), Vector
.size());
1196 ASSERT_EQ(4u, NumBuiltinElts(Vector
));
1197 for (size_t I
= 0; I
< Array
.size(); ++I
)
1198 EXPECT_EQ(Array
[I
], Vector
[I
]);
1202 TEST(SmallVectorTest
, ToVectorOf
) {
1203 To to1
{1}, to2
{2}, to3
{3};
1204 std::vector
<From
> StdVector
= {From(to1
), From(to2
), From(to3
)};
1206 llvm::SmallVector
<To
> Vector
= llvm::to_vector_of
<To
>(StdVector
);
1208 ASSERT_EQ(StdVector
.size(), Vector
.size());
1209 for (size_t I
= 0; I
< StdVector
.size(); ++I
)
1210 EXPECT_EQ(StdVector
[I
], Vector
[I
]);
1213 auto Vector
= llvm::to_vector_of
<To
, 4>(StdVector
);
1215 ASSERT_EQ(StdVector
.size(), Vector
.size());
1216 static_assert(NumBuiltinElts(Vector
) == 4u);
1217 for (size_t I
= 0; I
< StdVector
.size(); ++I
)
1218 EXPECT_EQ(StdVector
[I
], Vector
[I
]);
1222 template <class VectorT
>
1223 class SmallVectorReferenceInvalidationTest
: public SmallVectorTestBase
{
1225 const char *AssertionMessage
=
1226 "Attempting to reference an element of the vector in an operation \" "
1227 "\"that invalidates it";
1231 template <class T
> static bool isValueType() {
1232 return std::is_same
<T
, typename
VectorT::value_type
>::value
;
1235 void SetUp() override
{
1236 SmallVectorTestBase::SetUp();
1238 // Fill up the small size so that insertions move the elements.
1239 for (int I
= 0, E
= NumBuiltinElts(V
); I
!= E
; ++I
)
1240 V
.emplace_back(I
+ 1);
1244 // Test one type that's trivially copyable (int) and one that isn't
1245 // (Constructable) since reference invalidation may be fixed differently for
1247 using SmallVectorReferenceInvalidationTestTypes
=
1248 ::testing::Types
<SmallVector
<int, 3>, SmallVector
<Constructable
, 3>>;
1250 TYPED_TEST_SUITE(SmallVectorReferenceInvalidationTest
,
1251 SmallVectorReferenceInvalidationTestTypes
, );
1253 TYPED_TEST(SmallVectorReferenceInvalidationTest
, PushBack
) {
1254 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1256 int N
= NumBuiltinElts(V
);
1258 // Push back a reference to last element when growing from small storage.
1259 V
.push_back(V
.back());
1260 EXPECT_EQ(N
, V
.back());
1262 // Check that the old value is still there (not moved away).
1263 EXPECT_EQ(N
, V
[V
.size() - 2]);
1265 // Fill storage again.
1266 V
.back() = V
.size();
1267 while (V
.size() < V
.capacity())
1268 V
.push_back(V
.size() + 1);
1270 // Push back a reference to last element when growing from large storage.
1271 V
.push_back(V
.back());
1272 EXPECT_EQ(int(V
.size()) - 1, V
.back());
1275 TYPED_TEST(SmallVectorReferenceInvalidationTest
, PushBackMoved
) {
1276 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1278 int N
= NumBuiltinElts(V
);
1280 // Push back a reference to last element when growing from small storage.
1281 V
.push_back(std::move(V
.back()));
1282 EXPECT_EQ(N
, V
.back());
1283 if (this->template isValueType
<Constructable
>()) {
1284 // Check that the value was moved (not copied).
1285 EXPECT_EQ(0, V
[V
.size() - 2]);
1288 // Fill storage again.
1289 V
.back() = V
.size();
1290 while (V
.size() < V
.capacity())
1291 V
.push_back(V
.size() + 1);
1293 // Push back a reference to last element when growing from large storage.
1294 V
.push_back(std::move(V
.back()));
1296 // Check the values.
1297 EXPECT_EQ(int(V
.size()) - 1, V
.back());
1298 if (this->template isValueType
<Constructable
>()) {
1299 // Check the value got moved out.
1300 EXPECT_EQ(0, V
[V
.size() - 2]);
1304 TYPED_TEST(SmallVectorReferenceInvalidationTest
, Resize
) {
1307 int N
= NumBuiltinElts(V
);
1308 V
.resize(N
+ 1, V
.back());
1309 EXPECT_EQ(N
, V
.back());
1311 // Resize to add enough elements that V will grow again. If reference
1312 // invalidation breaks in the future, sanitizers should be able to catch a
1313 // use-after-free here.
1314 V
.resize(V
.capacity() + 1, V
.front());
1315 EXPECT_EQ(1, V
.back());
1318 TYPED_TEST(SmallVectorReferenceInvalidationTest
, Append
) {
1321 V
.append(1, V
.back());
1322 int N
= NumBuiltinElts(V
);
1323 EXPECT_EQ(N
, V
[N
- 1]);
1325 // Append enough more elements that V will grow again. This tests growing
1326 // when already in large mode.
1328 // If reference invalidation breaks in the future, sanitizers should be able
1329 // to catch a use-after-free here.
1330 V
.append(V
.capacity() - V
.size() + 1, V
.front());
1331 EXPECT_EQ(1, V
.back());
1334 TYPED_TEST(SmallVectorReferenceInvalidationTest
, AppendRange
) {
1337 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1338 EXPECT_DEATH(V
.append(V
.begin(), V
.begin() + 1), this->AssertionMessage
);
1340 ASSERT_EQ(3u, NumBuiltinElts(V
));
1341 ASSERT_EQ(3u, V
.size());
1343 ASSERT_EQ(2u, V
.size());
1345 // Confirm this checks for growth when there's more than one element
1347 EXPECT_DEATH(V
.append(V
.begin(), V
.end()), this->AssertionMessage
);
1351 TYPED_TEST(SmallVectorReferenceInvalidationTest
, Assign
) {
1352 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1355 int N
= NumBuiltinElts(V
);
1356 ASSERT_EQ(unsigned(N
), V
.size());
1357 ASSERT_EQ(unsigned(N
), V
.capacity());
1359 // Check assign that shrinks in small mode.
1360 V
.assign(1, V
.back());
1361 EXPECT_EQ(1u, V
.size());
1364 // Check assign that grows within small mode.
1365 ASSERT_LT(V
.size(), V
.capacity());
1366 V
.assign(V
.capacity(), V
.back());
1367 for (int I
= 0, E
= V
.size(); I
!= E
; ++I
) {
1370 // Reset to [1, 2, ...].
1374 // Check assign that grows to large mode.
1376 V
.assign(V
.capacity() + 1, V
[1]);
1377 for (int I
= 0, E
= V
.size(); I
!= E
; ++I
) {
1380 // Reset to [1, 2, ...].
1384 // Check assign that shrinks in large mode.
1389 TYPED_TEST(SmallVectorReferenceInvalidationTest
, AssignRange
) {
1391 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1392 EXPECT_DEATH(V
.assign(V
.begin(), V
.end()), this->AssertionMessage
);
1393 EXPECT_DEATH(V
.assign(V
.begin(), V
.end() - 1), this->AssertionMessage
);
1395 V
.assign(V
.begin(), V
.begin());
1396 EXPECT_TRUE(V
.empty());
1399 TYPED_TEST(SmallVectorReferenceInvalidationTest
, Insert
) {
1400 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1404 // Insert a reference to the back (not at end() or else insert delegates to
1405 // push_back()), growing out of small mode. Confirm the value was copied out
1406 // (moving out Constructable sets it to 0).
1407 V
.insert(V
.begin(), V
.back());
1408 EXPECT_EQ(int(V
.size() - 1), V
.front());
1409 EXPECT_EQ(int(V
.size() - 1), V
.back());
1411 // Fill up the vector again.
1412 while (V
.size() < V
.capacity())
1413 V
.push_back(V
.size() + 1);
1415 // Grow again from large storage to large storage.
1416 V
.insert(V
.begin(), V
.back());
1417 EXPECT_EQ(int(V
.size() - 1), V
.front());
1418 EXPECT_EQ(int(V
.size() - 1), V
.back());
1421 TYPED_TEST(SmallVectorReferenceInvalidationTest
, InsertMoved
) {
1422 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1426 // Insert a reference to the back (not at end() or else insert delegates to
1427 // push_back()), growing out of small mode. Confirm the value was copied out
1428 // (moving out Constructable sets it to 0).
1429 V
.insert(V
.begin(), std::move(V
.back()));
1430 EXPECT_EQ(int(V
.size() - 1), V
.front());
1431 if (this->template isValueType
<Constructable
>()) {
1432 // Check the value got moved out.
1433 EXPECT_EQ(0, V
.back());
1436 // Fill up the vector again.
1437 while (V
.size() < V
.capacity())
1438 V
.push_back(V
.size() + 1);
1440 // Grow again from large storage to large storage.
1441 V
.insert(V
.begin(), std::move(V
.back()));
1442 EXPECT_EQ(int(V
.size() - 1), V
.front());
1443 if (this->template isValueType
<Constructable
>()) {
1444 // Check the value got moved out.
1445 EXPECT_EQ(0, V
.back());
1449 TYPED_TEST(SmallVectorReferenceInvalidationTest
, InsertN
) {
1453 // Cover NumToInsert <= this->end() - I.
1454 V
.insert(V
.begin() + 1, 1, V
.back());
1455 int N
= NumBuiltinElts(V
);
1458 // Cover NumToInsert > this->end() - I, inserting enough elements that V will
1459 // also grow again; V.capacity() will be more elements than necessary but
1460 // it's a simple way to cover both conditions.
1462 // If reference invalidation breaks in the future, sanitizers should be able
1463 // to catch a use-after-free here.
1464 V
.insert(V
.begin(), V
.capacity(), V
.front());
1465 EXPECT_EQ(1, V
.front());
1468 TYPED_TEST(SmallVectorReferenceInvalidationTest
, InsertRange
) {
1471 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1472 EXPECT_DEATH(V
.insert(V
.begin(), V
.begin(), V
.begin() + 1),
1473 this->AssertionMessage
);
1475 ASSERT_EQ(3u, NumBuiltinElts(V
));
1476 ASSERT_EQ(3u, V
.size());
1478 ASSERT_EQ(2u, V
.size());
1480 // Confirm this checks for growth when there's more than one element
1482 EXPECT_DEATH(V
.insert(V
.begin(), V
.begin(), V
.end()), this->AssertionMessage
);
1486 TYPED_TEST(SmallVectorReferenceInvalidationTest
, EmplaceBack
) {
1487 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1489 int N
= NumBuiltinElts(V
);
1491 // Push back a reference to last element when growing from small storage.
1492 V
.emplace_back(V
.back());
1493 EXPECT_EQ(N
, V
.back());
1495 // Check that the old value is still there (not moved away).
1496 EXPECT_EQ(N
, V
[V
.size() - 2]);
1498 // Fill storage again.
1499 V
.back() = V
.size();
1500 while (V
.size() < V
.capacity())
1501 V
.push_back(V
.size() + 1);
1503 // Push back a reference to last element when growing from large storage.
1504 V
.emplace_back(V
.back());
1505 EXPECT_EQ(int(V
.size()) - 1, V
.back());
1508 template <class VectorT
>
1509 class SmallVectorInternalReferenceInvalidationTest
1510 : public SmallVectorTestBase
{
1512 const char *AssertionMessage
=
1513 "Attempting to reference an element of the vector in an operation \" "
1514 "\"that invalidates it";
1518 void SetUp() override
{
1519 SmallVectorTestBase::SetUp();
1521 // Fill up the small size so that insertions move the elements.
1522 for (int I
= 0, E
= NumBuiltinElts(V
); I
!= E
; ++I
)
1523 V
.emplace_back(I
+ 1, I
+ 1);
1527 // Test pairs of the same types from SmallVectorReferenceInvalidationTestTypes.
1528 using SmallVectorInternalReferenceInvalidationTestTypes
=
1529 ::testing::Types
<SmallVector
<std::pair
<int, int>, 3>,
1530 SmallVector
<std::pair
<Constructable
, Constructable
>, 3>>;
1532 TYPED_TEST_SUITE(SmallVectorInternalReferenceInvalidationTest
,
1533 SmallVectorInternalReferenceInvalidationTestTypes
, );
1535 TYPED_TEST(SmallVectorInternalReferenceInvalidationTest
, EmplaceBack
) {
1536 // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1538 int N
= NumBuiltinElts(V
);
1540 // Push back a reference to last element when growing from small storage.
1541 V
.emplace_back(V
.back().first
, V
.back().second
);
1542 EXPECT_EQ(N
, V
.back().first
);
1543 EXPECT_EQ(N
, V
.back().second
);
1545 // Check that the old value is still there (not moved away).
1546 EXPECT_EQ(N
, V
[V
.size() - 2].first
);
1547 EXPECT_EQ(N
, V
[V
.size() - 2].second
);
1549 // Fill storage again.
1550 V
.back().first
= V
.back().second
= V
.size();
1551 while (V
.size() < V
.capacity())
1552 V
.emplace_back(V
.size() + 1, V
.size() + 1);
1554 // Push back a reference to last element when growing from large storage.
1555 V
.emplace_back(V
.back().first
, V
.back().second
);
1556 EXPECT_EQ(int(V
.size()) - 1, V
.back().first
);
1557 EXPECT_EQ(int(V
.size()) - 1, V
.back().second
);