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