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