LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/ADT - SmallVector.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 63.7 % 182 116
Test Date: 2026-02-27 05:14:50 Functions: 69.3 % 137 95
Legend: Lines:     hit not hit

            Line data    Source code
       1              : //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===//
       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              : /// \file
      10              : /// This file defines the SmallVector class.
      11              : ///
      12              : //===----------------------------------------------------------------------===//
      13              : 
      14              : #ifndef LLVM_ADT_SMALLVECTOR_H
      15              : #define LLVM_ADT_SMALLVECTOR_H
      16              : 
      17              : #include "llvm/Support/Compiler.h"
      18              : #include "llvm/Support/type_traits.h"
      19              : #include <algorithm>
      20              : #include <cassert>
      21              : #include <cstddef>
      22              : #include <cstdint>
      23              : #include <cstdlib>
      24              : #include <cstring>
      25              : #include <functional>
      26              : #include <initializer_list>
      27              : #include <iterator>
      28              : #include <limits>
      29              : #include <memory>
      30              : #include <new>
      31              : #include <type_traits>
      32              : #include <utility>
      33              : 
      34              : namespace llvm {
      35              : 
      36              : template <typename T> class ArrayRef;
      37              : 
      38              : template <typename IteratorT> class iterator_range;
      39              : 
      40              : template <class Iterator>
      41              : using EnableIfConvertibleToInputIterator = std::enable_if_t<std::is_convertible<
      42              :     typename std::iterator_traits<Iterator>::iterator_category,
      43              :     std::input_iterator_tag>::value>;
      44              : 
      45              : /// This is all the stuff common to all SmallVectors.
      46              : ///
      47              : /// The template parameter specifies the type which should be used to hold the
      48              : /// Size and Capacity of the SmallVector, so it can be adjusted.
      49              : /// Using 32 bit size is desirable to shrink the size of the SmallVector.
      50              : /// Using 64 bit size is desirable for cases like SmallVector<char>, where a
      51              : /// 32 bit size would limit the vector to ~4GB. SmallVectors are used for
      52              : /// buffering bitcode output - which can exceed 4GB.
      53              : template <class Size_T> class SmallVectorBase {
      54              : protected:
      55              :   void *BeginX;
      56              :   Size_T Size = 0, Capacity;
      57              : 
      58              :   /// The maximum value of the Size_T used.
      59              :   static constexpr size_t SizeTypeMax() {
      60              :     return std::numeric_limits<Size_T>::max();
      61              :   }
      62              : 
      63              :   SmallVectorBase() = delete;
      64              :   SmallVectorBase(void *FirstEl, size_t TotalCapacity)
      65              :       : BeginX(FirstEl), Capacity(static_cast<Size_T>(TotalCapacity)) {}
      66              : 
      67              :   /// This is a helper for \a grow() that's out of line to reduce code
      68              :   /// duplication.  This function will report a fatal error if it can't grow at
      69              :   /// least to \p MinSize.
      70              :   void *mallocForGrow(void *FirstEl, size_t MinSize, size_t TSize,
      71              :                       size_t &NewCapacity);
      72              : 
      73              :   /// This is an implementation of the grow() method which only works
      74              :   /// on POD-like data types and is out of line to reduce code duplication.
      75              :   /// This function will report a fatal error if it cannot increase capacity.
      76              :   void grow_pod(void *FirstEl, size_t MinSize, size_t TSize);
      77              : 
      78              :   /// If vector was first created with capacity 0, getFirstEl() points to the
      79              :   /// memory right after, an area unallocated. If a subsequent allocation,
      80              :   /// that grows the vector, happens to return the same pointer as getFirstEl(),
      81              :   /// get a new allocation, otherwise isSmall() will falsely return that no
      82              :   /// allocation was done (true) and the memory will not be freed in the
      83              :   /// destructor. If a VSize is given (vector size), also copy that many
      84              :   /// elements to the new allocation - used if realloca fails to increase
      85              :   /// space, and happens to allocate precisely at BeginX.
      86              :   /// This is unlikely to be called often, but resolves a memory leak when the
      87              :   /// situation does occur.
      88              :   void *replaceAllocation(void *NewElts, size_t TSize, size_t NewCapacity,
      89              :                           size_t VSize = 0);
      90              : 
      91              : public:
      92              :   size_t size() const { return Size; }
      93              :   size_t capacity() const { return Capacity; }
      94              : 
      95              :   [[nodiscard]] bool empty() const { return !Size; }
      96              : 
      97              : protected:
      98              :   /// Set the array size to \p N, which the current array must have enough
      99              :   /// capacity for.
     100              :   ///
     101              :   /// This does not construct or destroy any elements in the vector.
     102              :   void set_size(size_t N) {
     103              :     assert(N <= capacity()); // implies no overflow in assignment
     104              :     Size = static_cast<Size_T>(N);
     105              :   }
     106              : 
     107              :   /// Set the array data pointer to \p Begin and capacity to \p N.
     108              :   ///
     109              :   /// This does not construct or destroy any elements in the vector.
     110              :   //  This does not clean up any existing allocation.
     111              :   void set_allocation_range(void *Begin, size_t N) {
     112              :     assert(N <= SizeTypeMax());
     113              :     BeginX = Begin;
     114              :     Capacity = static_cast<Size_T>(N);
     115              :   }
     116              : };
     117              : 
     118              : template <class T>
     119              : using SmallVectorSizeType =
     120              :     std::conditional_t<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t,
     121              :                        uint32_t>;
     122              : 
     123              : /// Figure out the offset of the first element.
     124              : template <class T, typename = void> struct SmallVectorAlignmentAndSize {
     125              :   alignas(SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof(
     126              :       SmallVectorBase<SmallVectorSizeType<T>>)];
     127              :   alignas(T) char FirstEl[sizeof(T)];
     128              : };
     129              : 
     130              : /// This is the part of SmallVectorTemplateBase which does not depend on whether
     131              : /// the type T is a POD. The extra dummy template argument is used by ArrayRef
     132              : /// to avoid unnecessarily requiring T to be complete.
     133              : template <typename T, typename = void>
     134              : class SmallVectorTemplateCommon
     135              :     : public SmallVectorBase<SmallVectorSizeType<T>> {
     136              :   using Base = SmallVectorBase<SmallVectorSizeType<T>>;
     137              : 
     138              : protected:
     139              :   /// Find the address of the first element.  For this pointer math to be valid
     140              :   /// with small-size of 0 for T with lots of alignment, it's important that
     141              :   /// SmallVectorStorage is properly-aligned even for small-size of 0.
     142       624164 :   void *getFirstEl() const {
     143              :     return const_cast<void *>(reinterpret_cast<const void *>(
     144              :         reinterpret_cast<const char *>(this) +
     145       624164 :         offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)));
     146              :   }
     147              :   // Space after 'FirstEl' is clobbered, do not add any instance vars after it.
     148              : 
     149       306646 :   SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}
     150              : 
     151         2286 :   void grow_pod(size_t MinSize, size_t TSize) {
     152         2286 :     Base::grow_pod(getFirstEl(), MinSize, TSize);
     153         2286 :   }
     154              : 
     155              :   /// Return true if this is a smallvector which has not had dynamic
     156              :   /// memory allocated for it.
     157       315232 :   bool isSmall() const { return this->BeginX == getFirstEl(); }
     158              : 
     159              :   /// Put this vector in a state of being small.
     160            0 :   void resetToSmall() {
     161            0 :     this->BeginX = getFirstEl();
     162            0 :     this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect.
     163            0 :   }
     164              : 
     165              :   /// Return true if V is an internal reference to the given range.
     166            0 :   bool isReferenceToRange(const void *V, const void *First, const void *Last) const {
     167              :     // Use std::less to avoid UB.
     168              :     std::less<> LessThan;
     169            0 :     return !LessThan(V, First) && LessThan(V, Last);
     170              :   }
     171              : 
     172              :   /// Return true if V is an internal reference to this vector.
     173            0 :   bool isReferenceToStorage(const void *V) const {
     174            0 :     return isReferenceToRange(V, this->begin(), this->end());
     175              :   }
     176              : 
     177              :   /// Return true if First and Last form a valid (possibly empty) range in this
     178              :   /// vector's storage.
     179              :   bool isRangeInStorage(const void *First, const void *Last) const {
     180              :     // Use std::less to avoid UB.
     181              :     std::less<> LessThan;
     182              :     return !LessThan(First, this->begin()) && !LessThan(Last, First) &&
     183              :            !LessThan(this->end(), Last);
     184              :   }
     185              : 
     186              :   /// Return true unless Elt will be invalidated by resizing the vector to
     187              :   /// NewSize.
     188              :   bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
     189              :     // Past the end.
     190              :     if (LLVM_LIKELY(!isReferenceToStorage(Elt)))
     191              :       return true;
     192              : 
     193              :     // Return false if Elt will be destroyed by shrinking.
     194              :     if (NewSize <= this->size())
     195              :       return Elt < this->begin() + NewSize;
     196              : 
     197              :     // Return false if we need to grow.
     198              :     return NewSize <= this->capacity();
     199              :   }
     200              : 
     201              :   /// Check whether Elt will be invalidated by resizing the vector to NewSize.
     202              :   void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) {
     203              :     assert(isSafeToReferenceAfterResize(Elt, NewSize) &&
     204              :            "Attempting to reference an element of the vector in an operation "
     205              :            "that invalidates it");
     206              :   }
     207              : 
     208              :   /// Check whether Elt will be invalidated by increasing the size of the
     209              :   /// vector by N.
     210              :   void assertSafeToAdd(const void *Elt, size_t N = 1) {
     211              :     this->assertSafeToReferenceAfterResize(Elt, this->size() + N);
     212              :   }
     213              : 
     214              :   /// Check whether any part of the range will be invalidated by clearing.
     215              :   void assertSafeToReferenceAfterClear(const T *From, const T *To) {
     216              :     if (From == To)
     217              :       return;
     218              :     this->assertSafeToReferenceAfterResize(From, 0);
     219              :     this->assertSafeToReferenceAfterResize(To - 1, 0);
     220              :   }
     221              :   template <
     222              :       class ItTy,
     223              :       std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
     224              :                        bool> = false>
     225              :   void assertSafeToReferenceAfterClear(ItTy, ItTy) {}
     226              : 
     227              :   /// Check whether any part of the range will be invalidated by growing.
     228              :   void assertSafeToAddRange(const T *From, const T *To) {
     229              :     if (From == To)
     230              :       return;
     231              :     this->assertSafeToAdd(From, To - From);
     232              :     this->assertSafeToAdd(To - 1, To - From);
     233              :   }
     234              :   template <
     235              :       class ItTy,
     236              :       std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value,
     237              :                        bool> = false>
     238              :   void assertSafeToAddRange(ItTy, ItTy) {}
     239              : 
     240              :   /// Reserve enough space to add one element, and return the updated element
     241              :   /// pointer in case it was a reference to the storage.
     242              :   template <class U>
     243       711540 :   static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt,
     244              :                                                    size_t N) {
     245       711540 :     size_t NewSize = This->size() + N;
     246       711540 :     if (LLVM_LIKELY(NewSize <= This->capacity()))
     247       709254 :       return &Elt;
     248              : 
     249         2286 :     bool ReferencesStorage = false;
     250         2286 :     int64_t Index = -1;
     251              :     if (!U::TakesParamByValue) {
     252            0 :       if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))) {
     253            0 :         ReferencesStorage = true;
     254            0 :         Index = &Elt - This->begin();
     255              :       }
     256              :     }
     257         2286 :     This->grow(NewSize);
     258         2286 :     return ReferencesStorage ? This->begin() + Index : &Elt;
     259              :   }
     260              : 
     261              : public:
     262              :   using size_type = size_t;
     263              :   using difference_type = ptrdiff_t;
     264              :   using value_type = T;
     265              :   using iterator = T *;
     266              :   using const_iterator = const T *;
     267              : 
     268              :   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
     269              :   using reverse_iterator = std::reverse_iterator<iterator>;
     270              : 
     271              :   using reference = T &;
     272              :   using const_reference = const T &;
     273              :   using pointer = T *;
     274              :   using const_pointer = const T *;
     275              : 
     276              :   using Base::capacity;
     277              :   using Base::empty;
     278              :   using Base::size;
     279              : 
     280              :   // forward iterator creation methods.
     281      2093208 :   iterator begin() { return (iterator)this->BeginX; }
     282        20833 :   const_iterator begin() const { return (const_iterator)this->BeginX; }
     283      1749471 :   iterator end() { return begin() + size(); }
     284         9914 :   const_iterator end() const { return begin() + size(); }
     285              : 
     286              :   // reverse iterator creation methods.
     287              :   reverse_iterator rbegin()            { return reverse_iterator(end()); }
     288              :   const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
     289              :   reverse_iterator rend()              { return reverse_iterator(begin()); }
     290              :   const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
     291              : 
     292              :   size_type size_in_bytes() const { return size() * sizeof(T); }
     293              :   size_type max_size() const {
     294              :     return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T));
     295              :   }
     296              : 
     297              :   size_t capacity_in_bytes() const { return capacity() * sizeof(T); }
     298              : 
     299              :   /// Return a pointer to the vector's buffer, even if empty().
     300              :   pointer data() { return pointer(begin()); }
     301              :   /// Return a pointer to the vector's buffer, even if empty().
     302         1005 :   const_pointer data() const { return const_pointer(begin()); }
     303              : 
     304              :   reference operator[](size_type idx) {
     305              :     assert(idx < size());
     306              :     return begin()[idx];
     307              :   }
     308              :   const_reference operator[](size_type idx) const {
     309              :     assert(idx < size());
     310              :     return begin()[idx];
     311              :   }
     312              : 
     313              :   reference front() {
     314              :     assert(!empty());
     315              :     return begin()[0];
     316              :   }
     317              :   const_reference front() const {
     318              :     assert(!empty());
     319              :     return begin()[0];
     320              :   }
     321              : 
     322       704863 :   reference back() {
     323       704863 :     assert(!empty());
     324       704863 :     return end()[-1];
     325              :   }
     326              :   const_reference back() const {
     327              :     assert(!empty());
     328              :     return end()[-1];
     329              :   }
     330              : };
     331              : 
     332              : /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put
     333              : /// method implementations that are designed to work with non-trivial T's.
     334              : ///
     335              : /// We approximate is_trivially_copyable with trivial move/copy construction and
     336              : /// trivial destruction. While the standard doesn't specify that you're allowed
     337              : /// copy these types with memcpy, there is no way for the type to observe this.
     338              : /// This catches the important case of std::pair<POD, POD>, which is not
     339              : /// trivially assignable.
     340              : template <typename T, bool = (std::is_trivially_copy_constructible<T>::value) &&
     341              :                              (std::is_trivially_move_constructible<T>::value) &&
     342              :                              std::is_trivially_destructible<T>::value>
     343              : class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
     344              :   friend class SmallVectorTemplateCommon<T>;
     345              : 
     346              : protected:
     347              :   static constexpr bool TakesParamByValue = false;
     348              :   using ValueParamT = const T &;
     349              : 
     350          108 :   SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
     351              : 
     352          108 :   static void destroy_range(T *S, T *E) {
     353          108 :     while (S != E) {
     354            0 :       --E;
     355            0 :       E->~T();
     356              :     }
     357          108 :   }
     358              : 
     359              :   /// Move the range [I, E) into the uninitialized memory starting with "Dest",
     360              :   /// constructing elements as needed.
     361              :   template<typename It1, typename It2>
     362            0 :   static void uninitialized_move(It1 I, It1 E, It2 Dest) {
     363            0 :     std::uninitialized_move(I, E, Dest);
     364            0 :   }
     365              : 
     366              :   /// Copy the range [I, E) onto the uninitialized memory starting with "Dest",
     367              :   /// constructing elements as needed.
     368              :   template<typename It1, typename It2>
     369              :   static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
     370              :     std::uninitialized_copy(I, E, Dest);
     371              :   }
     372              : 
     373              :   /// Grow the allocated memory (without initializing new elements), doubling
     374              :   /// the size of the allocated memory. Guarantees space for at least one more
     375              :   /// element, or MinSize more elements if specified.
     376              :   void grow(size_t MinSize = 0);
     377              : 
     378              :   /// Create a new allocation big enough for \p MinSize and pass back its size
     379              :   /// in \p NewCapacity. This is the first section of \a grow().
     380              :   T *mallocForGrow(size_t MinSize, size_t &NewCapacity);
     381              : 
     382              :   /// Move existing elements over to the new allocation \p NewElts, the middle
     383              :   /// section of \a grow().
     384              :   void moveElementsForGrow(T *NewElts);
     385              : 
     386              :   /// Transfer ownership of the allocation, finishing up \a grow().
     387              :   void takeAllocationForGrow(T *NewElts, size_t NewCapacity);
     388              : 
     389              :   /// Reserve enough space to add one element, and return the updated element
     390              :   /// pointer in case it was a reference to the storage.
     391          664 :   const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
     392          664 :     return this->reserveForParamAndGetAddressImpl(this, Elt, N);
     393              :   }
     394              : 
     395              :   /// Reserve enough space to add one element, and return the updated element
     396              :   /// pointer in case it was a reference to the storage.
     397         3961 :   T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
     398              :     return const_cast<T *>(
     399         3961 :         this->reserveForParamAndGetAddressImpl(this, Elt, N));
     400              :   }
     401              : 
     402              :   static T &&forward_value_param(T &&V) { return std::move(V); }
     403              :   static const T &forward_value_param(const T &V) { return V; }
     404              : 
     405              :   void growAndAssign(size_t NumElts, const T &Elt) {
     406              :     // Grow manually in case Elt is an internal reference.
     407              :     size_t NewCapacity;
     408              :     T *NewElts = mallocForGrow(NumElts, NewCapacity);
     409              :     std::uninitialized_fill_n(NewElts, NumElts, Elt);
     410              :     this->destroy_range(this->begin(), this->end());
     411              :     takeAllocationForGrow(NewElts, NewCapacity);
     412              :     this->set_size(NumElts);
     413              :   }
     414              : 
     415              :   template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
     416              :     // Grow manually in case one of Args is an internal reference.
     417              :     size_t NewCapacity;
     418              :     T *NewElts = mallocForGrow(0, NewCapacity);
     419              :     ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...);
     420              :     moveElementsForGrow(NewElts);
     421              :     takeAllocationForGrow(NewElts, NewCapacity);
     422              :     this->set_size(this->size() + 1);
     423              :     return this->back();
     424              :   }
     425              : 
     426              : public:
     427          664 :   void push_back(const T &Elt) {
     428          664 :     const T *EltPtr = reserveForParamAndGetAddress(Elt);
     429          664 :     ::new ((void *)this->end()) T(*EltPtr);
     430          664 :     this->set_size(this->size() + 1);
     431          664 :   }
     432              : 
     433         3961 :   void push_back(T &&Elt) {
     434         3961 :     T *EltPtr = reserveForParamAndGetAddress(Elt);
     435         3961 :     ::new ((void *)this->end()) T(::std::move(*EltPtr));
     436         3961 :     this->set_size(this->size() + 1);
     437         3961 :   }
     438              : 
     439         4625 :   void pop_back() {
     440         4625 :     this->set_size(this->size() - 1);
     441         4625 :     this->end()->~T();
     442         4625 :   }
     443              : };
     444              : 
     445              : // Define this out-of-line to dissuade the C++ compiler from inlining it.
     446              : template <typename T, bool TriviallyCopyable>
     447            0 : void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) {
     448              :   size_t NewCapacity;
     449            0 :   T *NewElts = mallocForGrow(MinSize, NewCapacity);
     450            0 :   moveElementsForGrow(NewElts);
     451            0 :   takeAllocationForGrow(NewElts, NewCapacity);
     452            0 : }
     453              : 
     454              : template <typename T, bool TriviallyCopyable>
     455            0 : T *SmallVectorTemplateBase<T, TriviallyCopyable>::mallocForGrow(
     456              :     size_t MinSize, size_t &NewCapacity) {
     457              :   return static_cast<T *>(
     458            0 :       SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow(
     459            0 :           this->getFirstEl(), MinSize, sizeof(T), NewCapacity));
     460              : }
     461              : 
     462              : // Define this out-of-line to dissuade the C++ compiler from inlining it.
     463              : template <typename T, bool TriviallyCopyable>
     464            0 : void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow(
     465              :     T *NewElts) {
     466              :   // Move the elements over.
     467            0 :   this->uninitialized_move(this->begin(), this->end(), NewElts);
     468              : 
     469              :   // Destroy the original elements.
     470            0 :   destroy_range(this->begin(), this->end());
     471            0 : }
     472              : 
     473              : // Define this out-of-line to dissuade the C++ compiler from inlining it.
     474              : template <typename T, bool TriviallyCopyable>
     475            0 : void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow(
     476              :     T *NewElts, size_t NewCapacity) {
     477              :   // If this wasn't grown from the inline copy, deallocate the old space.
     478            0 :   if (!this->isSmall())
     479            0 :     free(this->begin());
     480              : 
     481            0 :   this->set_allocation_range(NewElts, NewCapacity);
     482            0 : }
     483              : 
     484              : /// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put
     485              : /// method implementations that are designed to work with trivially copyable
     486              : /// T's. This allows using memcpy in place of copy/move construction and
     487              : /// skipping destruction.
     488              : template <typename T>
     489              : class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
     490              :   friend class SmallVectorTemplateCommon<T>;
     491              : 
     492              : protected:
     493              :   /// True if it's cheap enough to take parameters by value. Doing so avoids
     494              :   /// overhead related to mitigations for reference invalidation.
     495              :   static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *);
     496              : 
     497              :   /// Either const T& or T, depending on whether it's cheap enough to take
     498              :   /// parameters by value.
     499              :   using ValueParamT = std::conditional_t<TakesParamByValue, T, const T &>;
     500              : 
     501       306538 :   SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
     502              : 
     503              :   // No need to do a destroy loop for POD's.
     504       315124 :   static void destroy_range(T *, T *) {}
     505              : 
     506              :   /// Move the range [I, E) onto the uninitialized memory
     507              :   /// starting with "Dest", constructing elements into it as needed.
     508              :   template<typename It1, typename It2>
     509         8586 :   static void uninitialized_move(It1 I, It1 E, It2 Dest) {
     510              :     // Just do a copy.
     511         8586 :     uninitialized_copy(I, E, Dest);
     512         8586 :   }
     513              : 
     514              :   /// Copy the range [I, E) onto the uninitialized memory
     515              :   /// starting with "Dest", constructing elements into it as needed.
     516              :   template<typename It1, typename It2>
     517              :   static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
     518              :     // Arbitrary iterator types; just use the basic implementation.
     519              :     std::uninitialized_copy(I, E, Dest);
     520              :   }
     521              : 
     522              :   /// Copy the range [I, E) onto the uninitialized memory
     523              :   /// starting with "Dest", constructing elements into it as needed.
     524              :   template <typename T1, typename T2>
     525        13875 :   static void uninitialized_copy(
     526              :       T1 *I, T1 *E, T2 *Dest,
     527              :       std::enable_if_t<std::is_same<std::remove_const_t<T1>, T2>::value> * =
     528              :           nullptr) {
     529              :     // Use memcpy for PODs iterated by pointers (which includes SmallVector
     530              :     // iterators): std::uninitialized_copy optimizes to memmove, but we can
     531              :     // use memcpy here. Note that I and E are iterators and thus might be
     532              :     // invalid for memcpy if they are equal.
     533        13875 :     if (I != E)
     534        13875 :       memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T));
     535        13875 :   }
     536              : 
     537              :   /// Double the size of the allocated memory, guaranteeing space for at
     538              :   /// least one more element or MinSize if specified.
     539         2286 :   void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); }
     540              : 
     541              :   /// Reserve enough space to add one element, and return the updated element
     542              :   /// pointer in case it was a reference to the storage.
     543              :   const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) {
     544              :     return this->reserveForParamAndGetAddressImpl(this, Elt, N);
     545              :   }
     546              : 
     547              :   /// Reserve enough space to add one element, and return the updated element
     548              :   /// pointer in case it was a reference to the storage.
     549       706915 :   T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) {
     550              :     return const_cast<T *>(
     551       706915 :         this->reserveForParamAndGetAddressImpl(this, Elt, N));
     552              :   }
     553              : 
     554              :   /// Copy \p V or return a reference, depending on \a ValueParamT.
     555              :   static ValueParamT forward_value_param(ValueParamT V) { return V; }
     556              : 
     557              :   void growAndAssign(size_t NumElts, T Elt) {
     558              :     // Elt has been copied in case it's an internal reference, side-stepping
     559              :     // reference invalidation problems without losing the realloc optimization.
     560              :     this->set_size(0);
     561              :     this->grow(NumElts);
     562              :     std::uninitialized_fill_n(this->begin(), NumElts, Elt);
     563              :     this->set_size(NumElts);
     564              :   }
     565              : 
     566              :   template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) {
     567              :     // Use push_back with a copy in case Args has an internal reference,
     568              :     // side-stepping reference invalidation problems without losing the realloc
     569              :     // optimization.
     570              :     push_back(T(std::forward<ArgTypes>(Args)...));
     571              :     return this->back();
     572              :   }
     573              : 
     574              : public:
     575       706915 :   void push_back(ValueParamT Elt) {
     576       706915 :     const T *EltPtr = reserveForParamAndGetAddress(Elt);
     577       706915 :     memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T));
     578       706915 :     this->set_size(this->size() + 1);
     579       706915 :   }
     580              : 
     581       700238 :   void pop_back() { this->set_size(this->size() - 1); }
     582              : };
     583              : 
     584              : /// This class consists of common code factored out of the SmallVector class to
     585              : /// reduce code duplication based on the SmallVector 'N' template parameter.
     586              : template <typename T>
     587              : class SmallVectorImpl : public SmallVectorTemplateBase<T> {
     588              :   using SuperClass = SmallVectorTemplateBase<T>;
     589              : 
     590              : public:
     591              :   using iterator = typename SuperClass::iterator;
     592              :   using const_iterator = typename SuperClass::const_iterator;
     593              :   using reference = typename SuperClass::reference;
     594              :   using size_type = typename SuperClass::size_type;
     595              : 
     596              : protected:
     597              :   using SmallVectorTemplateBase<T>::TakesParamByValue;
     598              :   using ValueParamT = typename SuperClass::ValueParamT;
     599              : 
     600              :   // Default ctor - Initialize to empty.
     601       306646 :   explicit SmallVectorImpl(unsigned N)
     602       306646 :       : SmallVectorTemplateBase<T>(N) {}
     603              : 
     604            0 :   void assignRemote(SmallVectorImpl &&RHS) {
     605            0 :     this->destroy_range(this->begin(), this->end());
     606            0 :     if (!this->isSmall())
     607            0 :       free(this->begin());
     608            0 :     this->BeginX = RHS.BeginX;
     609            0 :     this->Size = RHS.Size;
     610            0 :     this->Capacity = RHS.Capacity;
     611            0 :     RHS.resetToSmall();
     612            0 :   }
     613              : 
     614       306646 :   ~SmallVectorImpl() {
     615              :     // Subclass has already destructed this vector's elements.
     616              :     // If this wasn't grown from the inline copy, deallocate the old space.
     617       306646 :     if (!this->isSmall())
     618         1419 :       free(this->begin());
     619       306646 :   }
     620              : 
     621              : public:
     622              :   SmallVectorImpl(const SmallVectorImpl &) = delete;
     623              : 
     624         8586 :   void clear() {
     625         8586 :     this->destroy_range(this->begin(), this->end());
     626         8586 :     this->Size = 0;
     627         8586 :   }
     628              : 
     629              : private:
     630              :   // Make set_size() private to avoid misuse in subclasses.
     631              :   using SuperClass::set_size;
     632              : 
     633              :   template <bool ForOverwrite> void resizeImpl(size_type N) {
     634              :     if (N == this->size())
     635              :       return;
     636              : 
     637              :     if (N < this->size()) {
     638              :       this->truncate(N);
     639              :       return;
     640              :     }
     641              : 
     642              :     this->reserve(N);
     643              :     for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
     644              :       if (ForOverwrite)
     645              :         new (&*I) T;
     646              :       else
     647              :         new (&*I) T();
     648              :     this->set_size(N);
     649              :   }
     650              : 
     651              : public:
     652              :   void resize(size_type N) { resizeImpl<false>(N); }
     653              : 
     654              :   /// Like resize, but \ref T is POD, the new values won't be initialized.
     655              :   void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
     656              : 
     657              :   /// Like resize, but requires that \p N is less than \a size().
     658              :   void truncate(size_type N) {
     659              :     assert(this->size() >= N && "Cannot increase size with truncate");
     660              :     this->destroy_range(this->begin() + N, this->end());
     661              :     this->set_size(N);
     662              :   }
     663              : 
     664              :   void resize(size_type N, ValueParamT NV) {
     665              :     if (N == this->size())
     666              :       return;
     667              : 
     668              :     if (N < this->size()) {
     669              :       this->truncate(N);
     670              :       return;
     671              :     }
     672              : 
     673              :     // N > this->size(). Defer to append.
     674              :     this->append(N - this->size(), NV);
     675              :   }
     676              : 
     677              :   void reserve(size_type N) {
     678              :     if (this->capacity() < N)
     679              :       this->grow(N);
     680              :   }
     681              : 
     682              :   void pop_back_n(size_type NumItems) {
     683              :     assert(this->size() >= NumItems);
     684              :     truncate(this->size() - NumItems);
     685              :   }
     686              : 
     687       704863 :   [[nodiscard]] T pop_back_val() {
     688       704863 :     T Result = ::std::move(this->back());
     689       704863 :     this->pop_back();
     690       704863 :     return Result;
     691            0 :   }
     692              : 
     693              :   void swap(SmallVectorImpl &RHS);
     694              : 
     695              :   /// Add the specified range to the end of the SmallVector.
     696              :   template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
     697              :   void append(ItTy in_start, ItTy in_end) {
     698              :     this->assertSafeToAddRange(in_start, in_end);
     699              :     size_type NumInputs = std::distance(in_start, in_end);
     700              :     this->reserve(this->size() + NumInputs);
     701              :     this->uninitialized_copy(in_start, in_end, this->end());
     702              :     this->set_size(this->size() + NumInputs);
     703              :   }
     704              : 
     705              :   /// Append \p NumInputs copies of \p Elt to the end.
     706              :   void append(size_type NumInputs, ValueParamT Elt) {
     707              :     const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs);
     708              :     std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr);
     709              :     this->set_size(this->size() + NumInputs);
     710              :   }
     711              : 
     712              :   void append(std::initializer_list<T> IL) {
     713              :     append(IL.begin(), IL.end());
     714              :   }
     715              : 
     716              :   void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); }
     717              : 
     718              :   void assign(size_type NumElts, ValueParamT Elt) {
     719              :     // Note that Elt could be an internal reference.
     720              :     if (NumElts > this->capacity()) {
     721              :       this->growAndAssign(NumElts, Elt);
     722              :       return;
     723              :     }
     724              : 
     725              :     // Assign over existing elements.
     726              :     std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt);
     727              :     if (NumElts > this->size())
     728              :       std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt);
     729              :     else if (NumElts < this->size())
     730              :       this->destroy_range(this->begin() + NumElts, this->end());
     731              :     this->set_size(NumElts);
     732              :   }
     733              : 
     734              :   // FIXME: Consider assigning over existing elements, rather than clearing &
     735              :   // re-initializing them - for all assign(...) variants.
     736              : 
     737              :   template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
     738              :   void assign(ItTy in_start, ItTy in_end) {
     739              :     this->assertSafeToReferenceAfterClear(in_start, in_end);
     740              :     clear();
     741              :     append(in_start, in_end);
     742              :   }
     743              : 
     744              :   void assign(std::initializer_list<T> IL) {
     745              :     clear();
     746              :     append(IL);
     747              :   }
     748              : 
     749              :   void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); }
     750              : 
     751              :   iterator erase(const_iterator CI) {
     752              :     // Just cast away constness because this is a non-const member function.
     753              :     iterator I = const_cast<iterator>(CI);
     754              : 
     755              :     assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.");
     756              : 
     757              :     iterator N = I;
     758              :     // Shift all elts down one.
     759              :     std::move(I+1, this->end(), I);
     760              :     // Drop the last elt.
     761              :     this->pop_back();
     762              :     return(N);
     763              :   }
     764              : 
     765              :   iterator erase(const_iterator CS, const_iterator CE) {
     766              :     // Just cast away constness because this is a non-const member function.
     767              :     iterator S = const_cast<iterator>(CS);
     768              :     iterator E = const_cast<iterator>(CE);
     769              : 
     770              :     assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.");
     771              : 
     772              :     iterator N = S;
     773              :     // Shift all elts down.
     774              :     iterator I = std::move(E, this->end(), S);
     775              :     // Drop the last elts.
     776              :     this->destroy_range(I, this->end());
     777              :     this->set_size(I - this->begin());
     778              :     return(N);
     779              :   }
     780              : 
     781              : private:
     782              :   template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) {
     783              :     // Callers ensure that ArgType is derived from T.
     784              :     static_assert(
     785              :         std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>,
     786              :                      T>::value,
     787              :         "ArgType must be derived from T!");
     788              : 
     789              :     if (I == this->end()) {  // Important special case for empty vector.
     790              :       this->push_back(::std::forward<ArgType>(Elt));
     791              :       return this->end()-1;
     792              :     }
     793              : 
     794              :     assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
     795              : 
     796              :     // Grow if necessary.
     797              :     size_t Index = I - this->begin();
     798              :     std::remove_reference_t<ArgType> *EltPtr =
     799              :         this->reserveForParamAndGetAddress(Elt);
     800              :     I = this->begin() + Index;
     801              : 
     802              :     ::new ((void*) this->end()) T(::std::move(this->back()));
     803              :     // Push everything else over.
     804              :     std::move_backward(I, this->end()-1, this->end());
     805              :     this->set_size(this->size() + 1);
     806              : 
     807              :     // If we just moved the element we're inserting, be sure to update
     808              :     // the reference (never happens if TakesParamByValue).
     809              :     static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value,
     810              :                   "ArgType must be 'T' when taking by value!");
     811              :     if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end()))
     812              :       ++EltPtr;
     813              : 
     814              :     *I = ::std::forward<ArgType>(*EltPtr);
     815              :     return I;
     816              :   }
     817              : 
     818              : public:
     819              :   iterator insert(iterator I, T &&Elt) {
     820              :     return insert_one_impl(I, this->forward_value_param(std::move(Elt)));
     821              :   }
     822              : 
     823              :   iterator insert(iterator I, const T &Elt) {
     824              :     return insert_one_impl(I, this->forward_value_param(Elt));
     825              :   }
     826              : 
     827              :   iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) {
     828              :     // Convert iterator to elt# to avoid invalidating iterator when we reserve()
     829              :     size_t InsertElt = I - this->begin();
     830              : 
     831              :     if (I == this->end()) {  // Important special case for empty vector.
     832              :       append(NumToInsert, Elt);
     833              :       return this->begin()+InsertElt;
     834              :     }
     835              : 
     836              :     assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
     837              : 
     838              :     // Ensure there is enough space, and get the (maybe updated) address of
     839              :     // Elt.
     840              :     const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert);
     841              : 
     842              :     // Uninvalidate the iterator.
     843              :     I = this->begin()+InsertElt;
     844              : 
     845              :     // If there are more elements between the insertion point and the end of the
     846              :     // range than there are being inserted, we can use a simple approach to
     847              :     // insertion.  Since we already reserved space, we know that this won't
     848              :     // reallocate the vector.
     849              :     if (size_t(this->end()-I) >= NumToInsert) {
     850              :       T *OldEnd = this->end();
     851              :       append(std::move_iterator<iterator>(this->end() - NumToInsert),
     852              :              std::move_iterator<iterator>(this->end()));
     853              : 
     854              :       // Copy the existing elements that get replaced.
     855              :       std::move_backward(I, OldEnd-NumToInsert, OldEnd);
     856              : 
     857              :       // If we just moved the element we're inserting, be sure to update
     858              :       // the reference (never happens if TakesParamByValue).
     859              :       if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
     860              :         EltPtr += NumToInsert;
     861              : 
     862              :       std::fill_n(I, NumToInsert, *EltPtr);
     863              :       return I;
     864              :     }
     865              : 
     866              :     // Otherwise, we're inserting more elements than exist already, and we're
     867              :     // not inserting at the end.
     868              : 
     869              :     // Move over the elements that we're about to overwrite.
     870              :     T *OldEnd = this->end();
     871              :     this->set_size(this->size() + NumToInsert);
     872              :     size_t NumOverwritten = OldEnd-I;
     873              :     this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
     874              : 
     875              :     // If we just moved the element we're inserting, be sure to update
     876              :     // the reference (never happens if TakesParamByValue).
     877              :     if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end())
     878              :       EltPtr += NumToInsert;
     879              : 
     880              :     // Replace the overwritten part.
     881              :     std::fill_n(I, NumOverwritten, *EltPtr);
     882              : 
     883              :     // Insert the non-overwritten middle part.
     884              :     std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr);
     885              :     return I;
     886              :   }
     887              : 
     888              :   template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
     889              :   iterator insert(iterator I, ItTy From, ItTy To) {
     890              :     // Convert iterator to elt# to avoid invalidating iterator when we reserve()
     891              :     size_t InsertElt = I - this->begin();
     892              : 
     893              :     if (I == this->end()) {  // Important special case for empty vector.
     894              :       append(From, To);
     895              :       return this->begin()+InsertElt;
     896              :     }
     897              : 
     898              :     assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.");
     899              : 
     900              :     // Check that the reserve that follows doesn't invalidate the iterators.
     901              :     this->assertSafeToAddRange(From, To);
     902              : 
     903              :     size_t NumToInsert = std::distance(From, To);
     904              : 
     905              :     // Ensure there is enough space.
     906              :     reserve(this->size() + NumToInsert);
     907              : 
     908              :     // Uninvalidate the iterator.
     909              :     I = this->begin()+InsertElt;
     910              : 
     911              :     // If there are more elements between the insertion point and the end of the
     912              :     // range than there are being inserted, we can use a simple approach to
     913              :     // insertion.  Since we already reserved space, we know that this won't
     914              :     // reallocate the vector.
     915              :     if (size_t(this->end()-I) >= NumToInsert) {
     916              :       T *OldEnd = this->end();
     917              :       append(std::move_iterator<iterator>(this->end() - NumToInsert),
     918              :              std::move_iterator<iterator>(this->end()));
     919              : 
     920              :       // Copy the existing elements that get replaced.
     921              :       std::move_backward(I, OldEnd-NumToInsert, OldEnd);
     922              : 
     923              :       std::copy(From, To, I);
     924              :       return I;
     925              :     }
     926              : 
     927              :     // Otherwise, we're inserting more elements than exist already, and we're
     928              :     // not inserting at the end.
     929              : 
     930              :     // Move over the elements that we're about to overwrite.
     931              :     T *OldEnd = this->end();
     932              :     this->set_size(this->size() + NumToInsert);
     933              :     size_t NumOverwritten = OldEnd-I;
     934              :     this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten);
     935              : 
     936              :     // Replace the overwritten part.
     937              :     for (T *J = I; NumOverwritten > 0; --NumOverwritten) {
     938              :       *J = *From;
     939              :       ++J; ++From;
     940              :     }
     941              : 
     942              :     // Insert the non-overwritten middle part.
     943              :     this->uninitialized_copy(From, To, OldEnd);
     944              :     return I;
     945              :   }
     946              : 
     947              :   void insert(iterator I, std::initializer_list<T> IL) {
     948              :     insert(I, IL.begin(), IL.end());
     949              :   }
     950              : 
     951              :   template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) {
     952              :     if (LLVM_UNLIKELY(this->size() >= this->capacity()))
     953              :       return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...);
     954              : 
     955              :     ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...);
     956              :     this->set_size(this->size() + 1);
     957              :     return this->back();
     958              :   }
     959              : 
     960              :   SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
     961              : 
     962              :   SmallVectorImpl &operator=(SmallVectorImpl &&RHS);
     963              : 
     964              :   bool operator==(const SmallVectorImpl &RHS) const {
     965              :     if (this->size() != RHS.size()) return false;
     966              :     return std::equal(this->begin(), this->end(), RHS.begin());
     967              :   }
     968              :   bool operator!=(const SmallVectorImpl &RHS) const {
     969              :     return !(*this == RHS);
     970              :   }
     971              : 
     972              :   bool operator<(const SmallVectorImpl &RHS) const {
     973              :     return std::lexicographical_compare(this->begin(), this->end(),
     974              :                                         RHS.begin(), RHS.end());
     975              :   }
     976              :   bool operator>(const SmallVectorImpl &RHS) const { return RHS < *this; }
     977              :   bool operator<=(const SmallVectorImpl &RHS) const { return !(*this > RHS); }
     978              :   bool operator>=(const SmallVectorImpl &RHS) const { return !(*this < RHS); }
     979              : };
     980              : 
     981              : template <typename T>
     982              : void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
     983              :   if (this == &RHS) return;
     984              : 
     985              :   // We can only avoid copying elements if neither vector is small.
     986              :   if (!this->isSmall() && !RHS.isSmall()) {
     987              :     std::swap(this->BeginX, RHS.BeginX);
     988              :     std::swap(this->Size, RHS.Size);
     989              :     std::swap(this->Capacity, RHS.Capacity);
     990              :     return;
     991              :   }
     992              :   this->reserve(RHS.size());
     993              :   RHS.reserve(this->size());
     994              : 
     995              :   // Swap the shared elements.
     996              :   size_t NumShared = this->size();
     997              :   if (NumShared > RHS.size()) NumShared = RHS.size();
     998              :   for (size_type i = 0; i != NumShared; ++i)
     999              :     std::swap((*this)[i], RHS[i]);
    1000              : 
    1001              :   // Copy over the extra elts.
    1002              :   if (this->size() > RHS.size()) {
    1003              :     size_t EltDiff = this->size() - RHS.size();
    1004              :     this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end());
    1005              :     RHS.set_size(RHS.size() + EltDiff);
    1006              :     this->destroy_range(this->begin()+NumShared, this->end());
    1007              :     this->set_size(NumShared);
    1008              :   } else if (RHS.size() > this->size()) {
    1009              :     size_t EltDiff = RHS.size() - this->size();
    1010              :     this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end());
    1011              :     this->set_size(this->size() + EltDiff);
    1012              :     this->destroy_range(RHS.begin()+NumShared, RHS.end());
    1013              :     RHS.set_size(NumShared);
    1014              :   }
    1015              : }
    1016              : 
    1017              : template <typename T>
    1018         5289 : SmallVectorImpl<T> &SmallVectorImpl<T>::
    1019              :   operator=(const SmallVectorImpl<T> &RHS) {
    1020              :   // Avoid self-assignment.
    1021         5289 :   if (this == &RHS) return *this;
    1022              : 
    1023              :   // If we already have sufficient space, assign the common elements, then
    1024              :   // destroy any excess.
    1025         5289 :   size_t RHSSize = RHS.size();
    1026         5289 :   size_t CurSize = this->size();
    1027         5289 :   if (CurSize >= RHSSize) {
    1028              :     // Assign common elements.
    1029              :     iterator NewEnd;
    1030            0 :     if (RHSSize)
    1031            0 :       NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin());
    1032              :     else
    1033            0 :       NewEnd = this->begin();
    1034              : 
    1035              :     // Destroy excess elements.
    1036            0 :     this->destroy_range(NewEnd, this->end());
    1037              : 
    1038              :     // Trim.
    1039            0 :     this->set_size(RHSSize);
    1040            0 :     return *this;
    1041              :   }
    1042              : 
    1043              :   // If we have to grow to have enough elements, destroy the current elements.
    1044              :   // This allows us to avoid copying them during the grow.
    1045              :   // FIXME: don't do this if they're efficiently moveable.
    1046         5289 :   if (this->capacity() < RHSSize) {
    1047              :     // Destroy current elements.
    1048            0 :     this->clear();
    1049            0 :     CurSize = 0;
    1050            0 :     this->grow(RHSSize);
    1051         5289 :   } else if (CurSize) {
    1052              :     // Otherwise, use assignment for the already-constructed elements.
    1053            0 :     std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin());
    1054              :   }
    1055              : 
    1056              :   // Copy construct the new elements in place.
    1057         5289 :   this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(),
    1058         5289 :                            this->begin()+CurSize);
    1059              : 
    1060              :   // Set end.
    1061         5289 :   this->set_size(RHSSize);
    1062         5289 :   return *this;
    1063              : }
    1064              : 
    1065              : template <typename T>
    1066         8586 : SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) {
    1067              :   // Avoid self-assignment.
    1068         8586 :   if (this == &RHS) return *this;
    1069              : 
    1070              :   // If the RHS isn't small, clear this vector and then steal its buffer.
    1071         8586 :   if (!RHS.isSmall()) {
    1072            0 :     this->assignRemote(std::move(RHS));
    1073            0 :     return *this;
    1074              :   }
    1075              : 
    1076              :   // If we already have sufficient space, assign the common elements, then
    1077              :   // destroy any excess.
    1078         8586 :   size_t RHSSize = RHS.size();
    1079         8586 :   size_t CurSize = this->size();
    1080         8586 :   if (CurSize >= RHSSize) {
    1081              :     // Assign common elements.
    1082            0 :     iterator NewEnd = this->begin();
    1083            0 :     if (RHSSize)
    1084            0 :       NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd);
    1085              : 
    1086              :     // Destroy excess elements and trim the bounds.
    1087            0 :     this->destroy_range(NewEnd, this->end());
    1088            0 :     this->set_size(RHSSize);
    1089              : 
    1090              :     // Clear the RHS.
    1091            0 :     RHS.clear();
    1092              : 
    1093            0 :     return *this;
    1094              :   }
    1095              : 
    1096              :   // If we have to grow to have enough elements, destroy the current elements.
    1097              :   // This allows us to avoid copying them during the grow.
    1098              :   // FIXME: this may not actually make any sense if we can efficiently move
    1099              :   // elements.
    1100         8586 :   if (this->capacity() < RHSSize) {
    1101              :     // Destroy current elements.
    1102            0 :     this->clear();
    1103            0 :     CurSize = 0;
    1104            0 :     this->grow(RHSSize);
    1105         8586 :   } else if (CurSize) {
    1106              :     // Otherwise, use assignment for the already-constructed elements.
    1107            0 :     std::move(RHS.begin(), RHS.begin()+CurSize, this->begin());
    1108              :   }
    1109              : 
    1110              :   // Move-construct the new elements in place.
    1111         8586 :   this->uninitialized_move(RHS.begin()+CurSize, RHS.end(),
    1112         8586 :                            this->begin()+CurSize);
    1113              : 
    1114              :   // Set end.
    1115         8586 :   this->set_size(RHSSize);
    1116              : 
    1117         8586 :   RHS.clear();
    1118         8586 :   return *this;
    1119              : }
    1120              : 
    1121              : /// Storage for the SmallVector elements.  This is specialized for the N=0 case
    1122              : /// to avoid allocating unnecessary storage.
    1123              : template <typename T, unsigned N>
    1124              : struct SmallVectorStorage {
    1125              :   alignas(T) char InlineElts[N * sizeof(T)];
    1126              : };
    1127              : 
    1128              : /// We need the storage to be properly aligned even for small-size of 0 so that
    1129              : /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is
    1130              : /// well-defined.
    1131              : template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {};
    1132              : 
    1133              : /// Forward declaration of SmallVector so that
    1134              : /// calculateSmallVectorDefaultInlinedElements can reference
    1135              : /// `sizeof(SmallVector<T, 0>)`.
    1136              : template <typename T, unsigned N> class LLVM_GSL_OWNER SmallVector;
    1137              : 
    1138              : /// Helper class for calculating the default number of inline elements for
    1139              : /// `SmallVector<T>`.
    1140              : ///
    1141              : /// This should be migrated to a constexpr function when our minimum
    1142              : /// compiler support is enough for multi-statement constexpr functions.
    1143              : template <typename T> struct CalculateSmallVectorDefaultInlinedElements {
    1144              :   // Parameter controlling the default number of inlined elements
    1145              :   // for `SmallVector<T>`.
    1146              :   //
    1147              :   // The default number of inlined elements ensures that
    1148              :   // 1. There is at least one inlined element.
    1149              :   // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless
    1150              :   // it contradicts 1.
    1151              :   static constexpr size_t kPreferredSmallVectorSizeof = 64;
    1152              : 
    1153              :   // static_assert that sizeof(T) is not "too big".
    1154              :   //
    1155              :   // Because our policy guarantees at least one inlined element, it is possible
    1156              :   // for an arbitrarily large inlined element to allocate an arbitrarily large
    1157              :   // amount of inline storage. We generally consider it an antipattern for a
    1158              :   // SmallVector to allocate an excessive amount of inline storage, so we want
    1159              :   // to call attention to these cases and make sure that users are making an
    1160              :   // intentional decision if they request a lot of inline storage.
    1161              :   //
    1162              :   // We want this assertion to trigger in pathological cases, but otherwise
    1163              :   // not be too easy to hit. To accomplish that, the cutoff is actually somewhat
    1164              :   // larger than kPreferredSmallVectorSizeof (otherwise,
    1165              :   // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that
    1166              :   // pattern seems useful in practice).
    1167              :   //
    1168              :   // One wrinkle is that this assertion is in theory non-portable, since
    1169              :   // sizeof(T) is in general platform-dependent. However, we don't expect this
    1170              :   // to be much of an issue, because most LLVM development happens on 64-bit
    1171              :   // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for
    1172              :   // 32-bit hosts, dodging the issue. The reverse situation, where development
    1173              :   // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a
    1174              :   // 64-bit host, is expected to be very rare.
    1175              :   static_assert(
    1176              :       sizeof(T) <= 256,
    1177              :       "You are trying to use a default number of inlined elements for "
    1178              :       "`SmallVector<T>` but `sizeof(T)` is really big! Please use an "
    1179              :       "explicit number of inlined elements with `SmallVector<T, N>` to make "
    1180              :       "sure you really want that much inline storage.");
    1181              : 
    1182              :   // Discount the size of the header itself when calculating the maximum inline
    1183              :   // bytes.
    1184              :   static constexpr size_t PreferredInlineBytes =
    1185              :       kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>);
    1186              :   static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T);
    1187              :   static constexpr size_t value =
    1188              :       NumElementsThatFit == 0 ? 1 : NumElementsThatFit;
    1189              : };
    1190              : 
    1191              : /// This is a 'vector' (really, a variable-sized array), optimized
    1192              : /// for the case when the array is small.  It contains some number of elements
    1193              : /// in-place, which allows it to avoid heap allocation when the actual number of
    1194              : /// elements is below that threshold.  This allows normal "small" cases to be
    1195              : /// fast without losing generality for large inputs.
    1196              : ///
    1197              : /// \note
    1198              : /// In the absence of a well-motivated choice for the number of inlined
    1199              : /// elements \p N, it is recommended to use \c SmallVector<T> (that is,
    1200              : /// omitting the \p N). This will choose a default number of inlined elements
    1201              : /// reasonable for allocation on the stack (for example, trying to keep \c
    1202              : /// sizeof(SmallVector<T>) around 64 bytes).
    1203              : ///
    1204              : /// \warning This does not attempt to be exception safe.
    1205              : ///
    1206              : /// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h
    1207              : template <typename T,
    1208              :           unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value>
    1209              : class LLVM_GSL_OWNER SmallVector : public SmallVectorImpl<T>,
    1210              :                                    SmallVectorStorage<T, N> {
    1211              : public:
    1212       293435 :   SmallVector() : SmallVectorImpl<T>(N) {}
    1213              : 
    1214       306646 :   ~SmallVector() {
    1215              :     // Destroy the constructed elements in the vector.
    1216       306646 :     this->destroy_range(this->begin(), this->end());
    1217       306646 :   }
    1218              : 
    1219              :   explicit SmallVector(size_t Size)
    1220              :     : SmallVectorImpl<T>(N) {
    1221              :     this->resize(Size);
    1222              :   }
    1223              : 
    1224              :   SmallVector(size_t Size, const T &Value)
    1225              :     : SmallVectorImpl<T>(N) {
    1226              :     this->assign(Size, Value);
    1227              :   }
    1228              : 
    1229              :   template <typename ItTy, typename = EnableIfConvertibleToInputIterator<ItTy>>
    1230              :   SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) {
    1231              :     this->append(S, E);
    1232              :   }
    1233              : 
    1234              :   template <typename RangeTy>
    1235              :   explicit SmallVector(const iterator_range<RangeTy> &R)
    1236              :       : SmallVectorImpl<T>(N) {
    1237              :     this->append(R.begin(), R.end());
    1238              :   }
    1239              : 
    1240              :   SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) {
    1241              :     this->append(IL);
    1242              :   }
    1243              : 
    1244              :   template <typename U,
    1245              :             typename = std::enable_if_t<std::is_convertible<U, T>::value>>
    1246              :   explicit SmallVector(ArrayRef<U> A) : SmallVectorImpl<T>(N) {
    1247              :     this->append(A.begin(), A.end());
    1248              :   }
    1249              : 
    1250         4625 :   SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) {
    1251         4625 :     if (!RHS.empty())
    1252         4625 :       SmallVectorImpl<T>::operator=(RHS);
    1253         4625 :   }
    1254              : 
    1255          664 :   SmallVector &operator=(const SmallVector &RHS) {
    1256          664 :     SmallVectorImpl<T>::operator=(RHS);
    1257          664 :     return *this;
    1258              :   }
    1259              : 
    1260         8586 :   SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) {
    1261         8586 :     if (!RHS.empty())
    1262         8586 :       SmallVectorImpl<T>::operator=(::std::move(RHS));
    1263         8586 :   }
    1264              : 
    1265              :   SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) {
    1266              :     if (!RHS.empty())
    1267              :       SmallVectorImpl<T>::operator=(::std::move(RHS));
    1268              :   }
    1269              : 
    1270              :   SmallVector &operator=(SmallVector &&RHS) {
    1271              :     if (N) {
    1272              :       SmallVectorImpl<T>::operator=(::std::move(RHS));
    1273              :       return *this;
    1274              :     }
    1275              :     // SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the
    1276              :     // case.
    1277              :     if (this == &RHS)
    1278              :       return *this;
    1279              :     if (RHS.empty()) {
    1280              :       this->destroy_range(this->begin(), this->end());
    1281              :       this->Size = 0;
    1282              :     } else {
    1283              :       this->assignRemote(std::move(RHS));
    1284              :     }
    1285              :     return *this;
    1286              :   }
    1287              : 
    1288              :   SmallVector &operator=(SmallVectorImpl<T> &&RHS) {
    1289              :     SmallVectorImpl<T>::operator=(::std::move(RHS));
    1290              :     return *this;
    1291              :   }
    1292              : 
    1293              :   SmallVector &operator=(std::initializer_list<T> IL) {
    1294              :     this->assign(IL);
    1295              :     return *this;
    1296              :   }
    1297              : };
    1298              : 
    1299              : template <typename T, unsigned N>
    1300              : inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
    1301              :   return X.capacity_in_bytes();
    1302              : }
    1303              : 
    1304              : template <typename RangeType>
    1305              : using ValueTypeFromRangeType =
    1306              :     std::remove_const_t<std::remove_reference_t<decltype(*std::begin(
    1307              :         std::declval<RangeType &>()))>>;
    1308              : 
    1309              : /// Given a range of type R, iterate the entire range and return a
    1310              : /// SmallVector with elements of the vector.  This is useful, for example,
    1311              : /// when you want to iterate a range and then sort the results.
    1312              : template <unsigned Size, typename R>
    1313              : SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R &&Range) {
    1314              :   return {std::begin(Range), std::end(Range)};
    1315              : }
    1316              : template <typename R>
    1317              : SmallVector<ValueTypeFromRangeType<R>> to_vector(R &&Range) {
    1318              :   return {std::begin(Range), std::end(Range)};
    1319              : }
    1320              : 
    1321              : template <typename Out, unsigned Size, typename R>
    1322              : SmallVector<Out, Size> to_vector_of(R &&Range) {
    1323              :   return {std::begin(Range), std::end(Range)};
    1324              : }
    1325              : 
    1326              : template <typename Out, typename R> SmallVector<Out> to_vector_of(R &&Range) {
    1327              :   return {std::begin(Range), std::end(Range)};
    1328              : }
    1329              : 
    1330              : // Explicit instantiations
    1331              : extern template class llvm::SmallVectorBase<uint32_t>;
    1332              : #if SIZE_MAX > UINT32_MAX
    1333              : extern template class llvm::SmallVectorBase<uint64_t>;
    1334              : #endif
    1335              : 
    1336              : } // end namespace llvm
    1337              : 
    1338              : namespace std {
    1339              : 
    1340              :   /// Implement std::swap in terms of SmallVector swap.
    1341              :   template<typename T>
    1342              :   inline void
    1343              :   swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) {
    1344              :     LHS.swap(RHS);
    1345              :   }
    1346              : 
    1347              :   /// Implement std::swap in terms of SmallVector swap.
    1348              :   template<typename T, unsigned N>
    1349              :   inline void
    1350              :   swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) {
    1351              :     LHS.swap(RHS);
    1352              :   }
    1353              : 
    1354              : } // end namespace std
    1355              : 
    1356              : #endif // LLVM_ADT_SMALLVECTOR_H
        

Generated by: LCOV version 2.0-1