xref: /llvm-project/llvm/unittests/ADT/SmallVectorTest.cpp (revision 9abac60309006db00eca0af406c2e16bef26807c)
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_CASE(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 // Assign test
489 TYPED_TEST(SmallVectorTest, AssignTest) {
490   SCOPED_TRACE("AssignTest");
491 
492   this->theVector.push_back(Constructable(1));
493   this->theVector.assign(2, Constructable(77));
494   this->assertValuesInOrder(this->theVector, 2u, 77, 77);
495 }
496 
497 // Assign test
498 TYPED_TEST(SmallVectorTest, AssignRangeTest) {
499   SCOPED_TRACE("AssignTest");
500 
501   this->theVector.push_back(Constructable(1));
502   int arr[] = {1, 2, 3};
503   this->theVector.assign(std::begin(arr), std::end(arr));
504   this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
505 }
506 
507 // Assign test
508 TYPED_TEST(SmallVectorTest, AssignNonIterTest) {
509   SCOPED_TRACE("AssignTest");
510 
511   this->theVector.push_back(Constructable(1));
512   this->theVector.assign(2, 7);
513   this->assertValuesInOrder(this->theVector, 2u, 7, 7);
514 }
515 
516 // Move-assign test
517 TYPED_TEST(SmallVectorTest, MoveAssignTest) {
518   SCOPED_TRACE("MoveAssignTest");
519 
520   // Set up our vector with a single element, but enough capacity for 4.
521   this->theVector.reserve(4);
522   this->theVector.push_back(Constructable(1));
523 
524   // Set up the other vector with 2 elements.
525   this->otherVector.push_back(Constructable(2));
526   this->otherVector.push_back(Constructable(3));
527 
528   // Move-assign from the other vector.
529   this->theVector = std::move(this->otherVector);
530 
531   // Make sure we have the right result.
532   this->assertValuesInOrder(this->theVector, 2u, 2, 3);
533 
534   // Make sure the # of constructor/destructor calls line up. There
535   // are two live objects after clearing the other vector.
536   this->otherVector.clear();
537   EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
538             Constructable::getNumDestructorCalls());
539 
540   // There shouldn't be any live objects any more.
541   this->theVector.clear();
542   EXPECT_EQ(Constructable::getNumConstructorCalls(),
543             Constructable::getNumDestructorCalls());
544 }
545 
546 // Erase a single element
547 TYPED_TEST(SmallVectorTest, EraseTest) {
548   SCOPED_TRACE("EraseTest");
549 
550   this->makeSequence(this->theVector, 1, 3);
551   const auto &theConstVector = this->theVector;
552   this->theVector.erase(theConstVector.begin());
553   this->assertValuesInOrder(this->theVector, 2u, 2, 3);
554 }
555 
556 // Erase a range of elements
557 TYPED_TEST(SmallVectorTest, EraseRangeTest) {
558   SCOPED_TRACE("EraseRangeTest");
559 
560   this->makeSequence(this->theVector, 1, 3);
561   const auto &theConstVector = this->theVector;
562   this->theVector.erase(theConstVector.begin(), theConstVector.begin() + 2);
563   this->assertValuesInOrder(this->theVector, 1u, 3);
564 }
565 
566 // Insert a single element.
567 TYPED_TEST(SmallVectorTest, InsertTest) {
568   SCOPED_TRACE("InsertTest");
569 
570   this->makeSequence(this->theVector, 1, 3);
571   typename TypeParam::iterator I =
572     this->theVector.insert(this->theVector.begin() + 1, Constructable(77));
573   EXPECT_EQ(this->theVector.begin() + 1, I);
574   this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
575 }
576 
577 // Insert a copy of a single element.
578 TYPED_TEST(SmallVectorTest, InsertCopy) {
579   SCOPED_TRACE("InsertTest");
580 
581   this->makeSequence(this->theVector, 1, 3);
582   Constructable C(77);
583   typename TypeParam::iterator I =
584       this->theVector.insert(this->theVector.begin() + 1, C);
585   EXPECT_EQ(this->theVector.begin() + 1, I);
586   this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
587 }
588 
589 // Insert repeated elements.
590 TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
591   SCOPED_TRACE("InsertRepeatedTest");
592 
593   this->makeSequence(this->theVector, 1, 4);
594   Constructable::reset();
595   auto I =
596       this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16));
597   // Move construct the top element into newly allocated space, and optionally
598   // reallocate the whole buffer, move constructing into it.
599   // FIXME: This is inefficient, we shouldn't move things into newly allocated
600   // space, then move them up/around, there should only be 2 or 4 move
601   // constructions here.
602   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
603               Constructable::getNumMoveConstructorCalls() == 6);
604   // Move assign the next two to shift them up and make a gap.
605   EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
606   // Copy construct the two new elements from the parameter.
607   EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
608   // All without any copy construction.
609   EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
610   EXPECT_EQ(this->theVector.begin() + 1, I);
611   this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4);
612 }
613 
614 TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) {
615   SCOPED_TRACE("InsertRepeatedTest");
616 
617   this->makeSequence(this->theVector, 1, 4);
618   Constructable::reset();
619   auto I = this->theVector.insert(this->theVector.begin() + 1, 2, 7);
620   EXPECT_EQ(this->theVector.begin() + 1, I);
621   this->assertValuesInOrder(this->theVector, 6u, 1, 7, 7, 2, 3, 4);
622 }
623 
624 TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
625   SCOPED_TRACE("InsertRepeatedTest");
626 
627   this->makeSequence(this->theVector, 1, 4);
628   Constructable::reset();
629   auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16));
630   // Just copy construct them into newly allocated space
631   EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
632   // Move everything across if reallocation is needed.
633   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
634               Constructable::getNumMoveConstructorCalls() == 4);
635   // Without ever moving or copying anything else.
636   EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
637   EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
638 
639   EXPECT_EQ(this->theVector.begin() + 4, I);
640   this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16);
641 }
642 
643 TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
644   SCOPED_TRACE("InsertRepeatedTest");
645 
646   this->makeSequence(this->theVector, 10, 15);
647 
648   // Empty insert.
649   EXPECT_EQ(this->theVector.end(),
650             this->theVector.insert(this->theVector.end(),
651                                    0, Constructable(42)));
652   EXPECT_EQ(this->theVector.begin() + 1,
653             this->theVector.insert(this->theVector.begin() + 1,
654                                    0, Constructable(42)));
655 }
656 
657 // Insert range.
658 TYPED_TEST(SmallVectorTest, InsertRangeTest) {
659   SCOPED_TRACE("InsertRangeTest");
660 
661   Constructable Arr[3] =
662     { Constructable(77), Constructable(77), Constructable(77) };
663 
664   this->makeSequence(this->theVector, 1, 3);
665   Constructable::reset();
666   auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3);
667   // Move construct the top 3 elements into newly allocated space.
668   // Possibly move the whole sequence into new space first.
669   // FIXME: This is inefficient, we shouldn't move things into newly allocated
670   // space, then move them up/around, there should only be 2 or 3 move
671   // constructions here.
672   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
673               Constructable::getNumMoveConstructorCalls() == 5);
674   // Copy assign the lower 2 new elements into existing space.
675   EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
676   // Copy construct the third element into newly allocated space.
677   EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
678   EXPECT_EQ(this->theVector.begin() + 1, I);
679   this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3);
680 }
681 
682 
683 TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
684   SCOPED_TRACE("InsertRangeTest");
685 
686   Constructable Arr[3] =
687     { Constructable(77), Constructable(77), Constructable(77) };
688 
689   this->makeSequence(this->theVector, 1, 3);
690 
691   // Insert at end.
692   Constructable::reset();
693   auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3);
694   // Copy construct the 3 elements into new space at the top.
695   EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
696   // Don't copy/move anything else.
697   EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
698   // Reallocation might occur, causing all elements to be moved into the new
699   // buffer.
700   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
701               Constructable::getNumMoveConstructorCalls() == 3);
702   EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
703   EXPECT_EQ(this->theVector.begin() + 3, I);
704   this->assertValuesInOrder(this->theVector, 6u,
705                             1, 2, 3, 77, 77, 77);
706 }
707 
708 TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
709   SCOPED_TRACE("InsertRangeTest");
710 
711   this->makeSequence(this->theVector, 1, 3);
712 
713   // Empty insert.
714   EXPECT_EQ(this->theVector.end(),
715             this->theVector.insert(this->theVector.end(),
716                                    this->theVector.begin(),
717                                    this->theVector.begin()));
718   EXPECT_EQ(this->theVector.begin() + 1,
719             this->theVector.insert(this->theVector.begin() + 1,
720                                    this->theVector.begin(),
721                                    this->theVector.begin()));
722 }
723 
724 // Comparison tests.
725 TYPED_TEST(SmallVectorTest, ComparisonTest) {
726   SCOPED_TRACE("ComparisonTest");
727 
728   this->makeSequence(this->theVector, 1, 3);
729   this->makeSequence(this->otherVector, 1, 3);
730 
731   EXPECT_TRUE(this->theVector == this->otherVector);
732   EXPECT_FALSE(this->theVector != this->otherVector);
733 
734   this->otherVector.clear();
735   this->makeSequence(this->otherVector, 2, 4);
736 
737   EXPECT_FALSE(this->theVector == this->otherVector);
738   EXPECT_TRUE(this->theVector != this->otherVector);
739 }
740 
741 // Constant vector tests.
742 TYPED_TEST(SmallVectorTest, ConstVectorTest) {
743   const TypeParam constVector;
744 
745   EXPECT_EQ(0u, constVector.size());
746   EXPECT_TRUE(constVector.empty());
747   EXPECT_TRUE(constVector.begin() == constVector.end());
748 }
749 
750 // Direct array access.
751 TYPED_TEST(SmallVectorTest, DirectVectorTest) {
752   EXPECT_EQ(0u, this->theVector.size());
753   this->theVector.reserve(4);
754   EXPECT_LE(4u, this->theVector.capacity());
755   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
756   this->theVector.push_back(1);
757   this->theVector.push_back(2);
758   this->theVector.push_back(3);
759   this->theVector.push_back(4);
760   EXPECT_EQ(4u, this->theVector.size());
761   EXPECT_EQ(8, Constructable::getNumConstructorCalls());
762   EXPECT_EQ(1, this->theVector[0].getValue());
763   EXPECT_EQ(2, this->theVector[1].getValue());
764   EXPECT_EQ(3, this->theVector[2].getValue());
765   EXPECT_EQ(4, this->theVector[3].getValue());
766 }
767 
768 TYPED_TEST(SmallVectorTest, IteratorTest) {
769   std::list<int> L;
770   this->theVector.insert(this->theVector.end(), L.begin(), L.end());
771 }
772 
773 template <typename InvalidType> class DualSmallVectorsTest;
774 
775 template <typename VectorT1, typename VectorT2>
776 class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase {
777 protected:
778   VectorT1 theVector;
779   VectorT2 otherVector;
780 
781   template <typename T, unsigned N>
782   static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; }
783 };
784 
785 typedef ::testing::Types<
786     // Small mode -> Small mode.
787     std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>,
788     // Small mode -> Big mode.
789     std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>,
790     // Big mode -> Small mode.
791     std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>,
792     // Big mode -> Big mode.
793     std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>>
794   > DualSmallVectorTestTypes;
795 
796 TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
797 
798 TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
799   SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
800 
801   // Set up our vector with four elements.
802   for (unsigned I = 0; I < 4; ++I)
803     this->otherVector.push_back(Constructable(I));
804 
805   const Constructable *OrigDataPtr = this->otherVector.data();
806 
807   // Move-assign from the other vector.
808   this->theVector =
809     std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector));
810 
811   // Make sure we have the right result.
812   this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3);
813 
814   // Make sure the # of constructor/destructor calls line up. There
815   // are two live objects after clearing the other vector.
816   this->otherVector.clear();
817   EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
818             Constructable::getNumDestructorCalls());
819 
820   // If the source vector (otherVector) was in small-mode, assert that we just
821   // moved the data pointer over.
822   EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 ||
823               this->theVector.data() == OrigDataPtr);
824 
825   // There shouldn't be any live objects any more.
826   this->theVector.clear();
827   EXPECT_EQ(Constructable::getNumConstructorCalls(),
828             Constructable::getNumDestructorCalls());
829 
830   // We shouldn't have copied anything in this whole process.
831   EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
832 }
833 
834 struct notassignable {
835   int &x;
836   notassignable(int &x) : x(x) {}
837 };
838 
839 TEST(SmallVectorCustomTest, NoAssignTest) {
840   int x = 0;
841   SmallVector<notassignable, 2> vec;
842   vec.push_back(notassignable(x));
843   x = 42;
844   EXPECT_EQ(42, vec.pop_back_val().x);
845 }
846 
847 struct MovedFrom {
848   bool hasValue;
849   MovedFrom() : hasValue(true) {
850   }
851   MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) {
852     m.hasValue = false;
853   }
854   MovedFrom &operator=(MovedFrom&& m) {
855     hasValue = m.hasValue;
856     m.hasValue = false;
857     return *this;
858   }
859 };
860 
861 TEST(SmallVectorTest, MidInsert) {
862   SmallVector<MovedFrom, 3> v;
863   v.push_back(MovedFrom());
864   v.insert(v.begin(), MovedFrom());
865   for (MovedFrom &m : v)
866     EXPECT_TRUE(m.hasValue);
867 }
868 
869 enum EmplaceableArgState {
870   EAS_Defaulted,
871   EAS_Arg,
872   EAS_LValue,
873   EAS_RValue,
874   EAS_Failure
875 };
876 template <int I> struct EmplaceableArg {
877   EmplaceableArgState State;
878   EmplaceableArg() : State(EAS_Defaulted) {}
879   EmplaceableArg(EmplaceableArg &&X)
880       : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {}
881   EmplaceableArg(EmplaceableArg &X)
882       : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {}
883 
884   explicit EmplaceableArg(bool) : State(EAS_Arg) {}
885 
886 private:
887   EmplaceableArg &operator=(EmplaceableArg &&) = delete;
888   EmplaceableArg &operator=(const EmplaceableArg &) = delete;
889 };
890 
891 enum EmplaceableState { ES_Emplaced, ES_Moved };
892 struct Emplaceable {
893   EmplaceableArg<0> A0;
894   EmplaceableArg<1> A1;
895   EmplaceableArg<2> A2;
896   EmplaceableArg<3> A3;
897   EmplaceableState State;
898 
899   Emplaceable() : State(ES_Emplaced) {}
900 
901   template <class A0Ty>
902   explicit Emplaceable(A0Ty &&A0)
903       : A0(std::forward<A0Ty>(A0)), State(ES_Emplaced) {}
904 
905   template <class A0Ty, class A1Ty>
906   Emplaceable(A0Ty &&A0, A1Ty &&A1)
907       : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
908         State(ES_Emplaced) {}
909 
910   template <class A0Ty, class A1Ty, class A2Ty>
911   Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2)
912       : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
913         A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {}
914 
915   template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
916   Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3)
917       : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
918         A2(std::forward<A2Ty>(A2)), A3(std::forward<A3Ty>(A3)),
919         State(ES_Emplaced) {}
920 
921   Emplaceable(Emplaceable &&) : State(ES_Moved) {}
922   Emplaceable &operator=(Emplaceable &&) {
923     State = ES_Moved;
924     return *this;
925   }
926 
927 private:
928   Emplaceable(const Emplaceable &) = delete;
929   Emplaceable &operator=(const Emplaceable &) = delete;
930 };
931 
932 TEST(SmallVectorTest, EmplaceBack) {
933   EmplaceableArg<0> A0(true);
934   EmplaceableArg<1> A1(true);
935   EmplaceableArg<2> A2(true);
936   EmplaceableArg<3> A3(true);
937   {
938     SmallVector<Emplaceable, 3> V;
939     Emplaceable &back = V.emplace_back();
940     EXPECT_TRUE(&back == &V.back());
941     EXPECT_TRUE(V.size() == 1);
942     EXPECT_TRUE(back.State == ES_Emplaced);
943     EXPECT_TRUE(back.A0.State == EAS_Defaulted);
944     EXPECT_TRUE(back.A1.State == EAS_Defaulted);
945     EXPECT_TRUE(back.A2.State == EAS_Defaulted);
946     EXPECT_TRUE(back.A3.State == EAS_Defaulted);
947   }
948   {
949     SmallVector<Emplaceable, 3> V;
950     Emplaceable &back = V.emplace_back(std::move(A0));
951     EXPECT_TRUE(&back == &V.back());
952     EXPECT_TRUE(V.size() == 1);
953     EXPECT_TRUE(back.State == ES_Emplaced);
954     EXPECT_TRUE(back.A0.State == EAS_RValue);
955     EXPECT_TRUE(back.A1.State == EAS_Defaulted);
956     EXPECT_TRUE(back.A2.State == EAS_Defaulted);
957     EXPECT_TRUE(back.A3.State == EAS_Defaulted);
958   }
959   {
960     SmallVector<Emplaceable, 3> V;
961     Emplaceable &back = V.emplace_back(A0);
962     EXPECT_TRUE(&back == &V.back());
963     EXPECT_TRUE(V.size() == 1);
964     EXPECT_TRUE(back.State == ES_Emplaced);
965     EXPECT_TRUE(back.A0.State == EAS_LValue);
966     EXPECT_TRUE(back.A1.State == EAS_Defaulted);
967     EXPECT_TRUE(back.A2.State == EAS_Defaulted);
968     EXPECT_TRUE(back.A3.State == EAS_Defaulted);
969   }
970   {
971     SmallVector<Emplaceable, 3> V;
972     Emplaceable &back = V.emplace_back(A0, A1);
973     EXPECT_TRUE(&back == &V.back());
974     EXPECT_TRUE(V.size() == 1);
975     EXPECT_TRUE(back.State == ES_Emplaced);
976     EXPECT_TRUE(back.A0.State == EAS_LValue);
977     EXPECT_TRUE(back.A1.State == EAS_LValue);
978     EXPECT_TRUE(back.A2.State == EAS_Defaulted);
979     EXPECT_TRUE(back.A3.State == EAS_Defaulted);
980   }
981   {
982     SmallVector<Emplaceable, 3> V;
983     Emplaceable &back = V.emplace_back(std::move(A0), std::move(A1));
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_RValue);
988     EXPECT_TRUE(back.A1.State == EAS_RValue);
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), A1, std::move(A2), A3);
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_LValue);
1000     EXPECT_TRUE(back.A2.State == EAS_RValue);
1001     EXPECT_TRUE(back.A3.State == EAS_LValue);
1002   }
1003   {
1004     SmallVector<int, 1> V;
1005     V.emplace_back();
1006     V.emplace_back(42);
1007     EXPECT_EQ(2U, V.size());
1008     EXPECT_EQ(0, V[0]);
1009     EXPECT_EQ(42, V[1]);
1010   }
1011 }
1012 
1013 TEST(SmallVectorTest, DefaultInlinedElements) {
1014   SmallVector<int> V;
1015   EXPECT_TRUE(V.empty());
1016   V.push_back(7);
1017   EXPECT_EQ(V[0], 7);
1018 
1019   // Check that at least a couple layers of nested SmallVector<T>'s are allowed
1020   // by the default inline elements policy. This pattern happens in practice
1021   // with some frequency, and it seems fairly harmless even though each layer of
1022   // SmallVector's will grow the total sizeof by a vector header beyond the
1023   // "preferred" maximum sizeof.
1024   SmallVector<SmallVector<SmallVector<int>>> NestedV;
1025   NestedV.emplace_back().emplace_back().emplace_back(42);
1026   EXPECT_EQ(NestedV[0][0][0], 42);
1027 }
1028 
1029 TEST(SmallVectorTest, InitializerList) {
1030   SmallVector<int, 2> V1 = {};
1031   EXPECT_TRUE(V1.empty());
1032   V1 = {0, 0};
1033   EXPECT_TRUE(makeArrayRef(V1).equals({0, 0}));
1034   V1 = {-1, -1};
1035   EXPECT_TRUE(makeArrayRef(V1).equals({-1, -1}));
1036 
1037   SmallVector<int, 2> V2 = {1, 2, 3, 4};
1038   EXPECT_TRUE(makeArrayRef(V2).equals({1, 2, 3, 4}));
1039   V2.assign({4});
1040   EXPECT_TRUE(makeArrayRef(V2).equals({4}));
1041   V2.append({3, 2});
1042   EXPECT_TRUE(makeArrayRef(V2).equals({4, 3, 2}));
1043   V2.insert(V2.begin() + 1, 5);
1044   EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2}));
1045 }
1046 
1047 template <class VectorT>
1048 class SmallVectorReferenceInvalidationTest : public SmallVectorTestBase {
1049 protected:
1050   const char *AssertionMessage =
1051       "Attempting to reference an element of the vector in an operation \" "
1052       "\"that invalidates it";
1053 
1054   VectorT V;
1055 
1056   template <typename T, unsigned N>
1057   static unsigned NumBuiltinElts(const SmallVector<T, N> &) {
1058     return N;
1059   }
1060 
1061   template <class T> static bool isValueType() {
1062     return std::is_same<T, typename VectorT::value_type>::value;
1063   }
1064 
1065   void SetUp() override {
1066     SmallVectorTestBase::SetUp();
1067 
1068     // Fill up the small size so that insertions move the elements.
1069     for (int I = 0, E = NumBuiltinElts(V); I != E; ++I)
1070       V.emplace_back(I + 1);
1071   }
1072 };
1073 
1074 // Test one type that's trivially copyable (int) and one that isn't
1075 // (Constructable) since reference invalidation may be fixed differently for
1076 // each.
1077 using SmallVectorReferenceInvalidationTestTypes =
1078     ::testing::Types<SmallVector<int, 3>, SmallVector<Constructable, 3>>;
1079 
1080 TYPED_TEST_CASE(SmallVectorReferenceInvalidationTest,
1081                 SmallVectorReferenceInvalidationTestTypes);
1082 
1083 TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBack) {
1084   // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1085   auto &V = this->V;
1086   int N = this->NumBuiltinElts(V);
1087 
1088   // Push back a reference to last element when growing from small storage.
1089   V.push_back(V.back());
1090   EXPECT_EQ(N, V.back());
1091 
1092   // Check that the old value is still there (not moved away).
1093   EXPECT_EQ(N, V[V.size() - 2]);
1094 
1095   // Fill storage again.
1096   V.back() = V.size();
1097   while (V.size() < V.capacity())
1098     V.push_back(V.size() + 1);
1099 
1100   // Push back a reference to last element when growing from large storage.
1101   V.push_back(V.back());
1102   EXPECT_EQ(int(V.size()) - 1, V.back());
1103 }
1104 
1105 TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBackMoved) {
1106   // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1107   auto &V = this->V;
1108   int N = this->NumBuiltinElts(V);
1109 
1110   // Push back a reference to last element when growing from small storage.
1111   V.push_back(std::move(V.back()));
1112   EXPECT_EQ(N, V.back());
1113   if (this->template isValueType<Constructable>()) {
1114     // Check that the value was moved (not copied).
1115     EXPECT_EQ(0, V[V.size() - 2]);
1116   }
1117 
1118   // Fill storage again.
1119   V.back() = V.size();
1120   while (V.size() < V.capacity())
1121     V.push_back(V.size() + 1);
1122 
1123   // Push back a reference to last element when growing from large storage.
1124   V.push_back(std::move(V.back()));
1125 
1126   // Check the values.
1127   EXPECT_EQ(int(V.size()) - 1, V.back());
1128   if (this->template isValueType<Constructable>()) {
1129     // Check the value got moved out.
1130     EXPECT_EQ(0, V[V.size() - 2]);
1131   }
1132 }
1133 
1134 TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) {
1135   auto &V = this->V;
1136   (void)V;
1137   int N = this->NumBuiltinElts(V);
1138 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1139   EXPECT_DEATH(V.resize(N + 1, V.back()), this->AssertionMessage);
1140 #endif
1141 
1142   // No assertion when shrinking, since the parameter isn't accessed.
1143   V.resize(N - 1, V.back());
1144 }
1145 
1146 TYPED_TEST(SmallVectorReferenceInvalidationTest, Append) {
1147   auto &V = this->V;
1148   (void)V;
1149 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1150   EXPECT_DEATH(V.append(1, V.back()), this->AssertionMessage);
1151 #endif
1152 }
1153 
1154 TYPED_TEST(SmallVectorReferenceInvalidationTest, AppendRange) {
1155   auto &V = this->V;
1156   (void)V;
1157 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1158   EXPECT_DEATH(V.append(V.begin(), V.begin() + 1), this->AssertionMessage);
1159 
1160   ASSERT_EQ(3u, this->NumBuiltinElts(V));
1161   ASSERT_EQ(3u, V.size());
1162   V.pop_back();
1163   ASSERT_EQ(2u, V.size());
1164 
1165   // Confirm this checks for growth when there's more than one element
1166   // appended.
1167   EXPECT_DEATH(V.append(V.begin(), V.end()), this->AssertionMessage);
1168 #endif
1169 }
1170 
1171 TYPED_TEST(SmallVectorReferenceInvalidationTest, Assign) {
1172   auto &V = this->V;
1173   (void)V;
1174 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1175   // Regardless of capacity, assign should never reference an internal element.
1176   EXPECT_DEATH(V.assign(1, V.back()), this->AssertionMessage);
1177   EXPECT_DEATH(V.assign(this->NumBuiltinElts(V), V.back()),
1178                this->AssertionMessage);
1179   EXPECT_DEATH(V.assign(this->NumBuiltinElts(V) + 1, V.back()),
1180                this->AssertionMessage);
1181 #endif
1182 }
1183 
1184 TYPED_TEST(SmallVectorReferenceInvalidationTest, AssignRange) {
1185   auto &V = this->V;
1186 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1187   EXPECT_DEATH(V.assign(V.begin(), V.end()), this->AssertionMessage);
1188   EXPECT_DEATH(V.assign(V.begin(), V.end() - 1), this->AssertionMessage);
1189 #endif
1190   V.assign(V.begin(), V.begin());
1191   EXPECT_TRUE(V.empty());
1192 }
1193 
1194 TYPED_TEST(SmallVectorReferenceInvalidationTest, Insert) {
1195   // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1196   auto &V = this->V;
1197   (void)V;
1198 
1199   // Insert a reference to the back (not at end() or else insert delegates to
1200   // push_back()), growing out of small mode. Confirm the value was copied out
1201   // (moving out Constructable sets it to 0).
1202   V.insert(V.begin(), V.back());
1203   EXPECT_EQ(int(V.size() - 1), V.front());
1204   EXPECT_EQ(int(V.size() - 1), V.back());
1205 
1206   // Fill up the vector again.
1207   while (V.size() < V.capacity())
1208     V.push_back(V.size() + 1);
1209 
1210   // Grow again from large storage to large storage.
1211   V.insert(V.begin(), V.back());
1212   EXPECT_EQ(int(V.size() - 1), V.front());
1213   EXPECT_EQ(int(V.size() - 1), V.back());
1214 }
1215 
1216 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertMoved) {
1217   // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode.
1218   auto &V = this->V;
1219   (void)V;
1220 
1221   // Insert a reference to the back (not at end() or else insert delegates to
1222   // push_back()), growing out of small mode. Confirm the value was copied out
1223   // (moving out Constructable sets it to 0).
1224   V.insert(V.begin(), std::move(V.back()));
1225   EXPECT_EQ(int(V.size() - 1), V.front());
1226   if (this->template isValueType<Constructable>()) {
1227     // Check the value got moved out.
1228     EXPECT_EQ(0, V.back());
1229   }
1230 
1231   // Fill up the vector again.
1232   while (V.size() < V.capacity())
1233     V.push_back(V.size() + 1);
1234 
1235   // Grow again from large storage to large storage.
1236   V.insert(V.begin(), std::move(V.back()));
1237   EXPECT_EQ(int(V.size() - 1), V.front());
1238   if (this->template isValueType<Constructable>()) {
1239     // Check the value got moved out.
1240     EXPECT_EQ(0, V.back());
1241   }
1242 }
1243 
1244 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertN) {
1245   auto &V = this->V;
1246   (void)V;
1247 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1248   EXPECT_DEATH(V.insert(V.begin(), 2, V.back()), this->AssertionMessage);
1249 #endif
1250 }
1251 
1252 TYPED_TEST(SmallVectorReferenceInvalidationTest, InsertRange) {
1253   auto &V = this->V;
1254   (void)V;
1255 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1256   EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.begin() + 1),
1257                this->AssertionMessage);
1258 
1259   ASSERT_EQ(3u, this->NumBuiltinElts(V));
1260   ASSERT_EQ(3u, V.size());
1261   V.pop_back();
1262   ASSERT_EQ(2u, V.size());
1263 
1264   // Confirm this checks for growth when there's more than one element
1265   // inserted.
1266   EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.end()), this->AssertionMessage);
1267 #endif
1268 }
1269 
1270 TYPED_TEST(SmallVectorReferenceInvalidationTest, EmplaceBack) {
1271   auto &V = this->V;
1272   (void)V;
1273 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1274   EXPECT_DEATH(V.emplace_back(V.back()), this->AssertionMessage);
1275 #endif
1276 }
1277 
1278 template <class VectorT>
1279 class SmallVectorInternalReferenceInvalidationTest
1280     : public SmallVectorTestBase {
1281 protected:
1282   const char *AssertionMessage =
1283       "Attempting to reference an element of the vector in an operation \" "
1284       "\"that invalidates it";
1285 
1286   VectorT V;
1287 
1288   template <typename T, unsigned N>
1289   static unsigned NumBuiltinElts(const SmallVector<T, N> &) {
1290     return N;
1291   }
1292 
1293   void SetUp() override {
1294     SmallVectorTestBase::SetUp();
1295 
1296     // Fill up the small size so that insertions move the elements.
1297     V.push_back(std::make_pair(0, 0));
1298   }
1299 };
1300 
1301 // Test pairs of the same types from SmallVectorReferenceInvalidationTestTypes.
1302 using SmallVectorInternalReferenceInvalidationTestTypes =
1303     ::testing::Types<SmallVector<std::pair<int, int>, 1>,
1304                      SmallVector<std::pair<Constructable, Constructable>, 1>>;
1305 
1306 TYPED_TEST_CASE(SmallVectorInternalReferenceInvalidationTest,
1307                 SmallVectorInternalReferenceInvalidationTestTypes);
1308 
1309 TYPED_TEST(SmallVectorInternalReferenceInvalidationTest, EmplaceBack) {
1310   auto &V = this->V;
1311   (void)V;
1312 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
1313   EXPECT_DEATH(V.emplace_back(V.back().first, 0), this->AssertionMessage);
1314   EXPECT_DEATH(V.emplace_back(0, V.back().second), this->AssertionMessage);
1315 #endif
1316 }
1317 
1318 } // end namespace
1319