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