LCOV - code coverage report
Current view: top level - gcc - vec.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.7 % 603 577
Test Date: 2026-02-28 14:20:25 Functions: 82.4 % 5614 4624
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Vector API for GNU compiler.
       2              :    Copyright (C) 2004-2026 Free Software Foundation, Inc.
       3              :    Contributed by Nathan Sidwell <nathan@codesourcery.com>
       4              :    Re-implemented in C++ by Diego Novillo <dnovillo@google.com>
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it under
       9              : the terms of the GNU General Public License as published by the Free
      10              : Software Foundation; either version 3, or (at your option) any later
      11              : version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : #ifndef GCC_VEC_H
      23              : #define GCC_VEC_H
      24              : 
      25              : /* Some gen* file have no ggc support as the header file gtype-desc.h is
      26              :    missing.  Provide these definitions in case ggc.h has not been included.
      27              :    This is not a problem because any code that runs before gengtype is built
      28              :    will never need to use GC vectors.*/
      29              : 
      30              : extern void ggc_free (void *);
      31              : extern size_t ggc_round_alloc_size (size_t requested_size);
      32              : extern void *ggc_realloc (void *, size_t MEM_STAT_DECL);
      33              : 
      34              : /* Templated vector type and associated interfaces.
      35              : 
      36              :    The interface functions are typesafe and use inline functions,
      37              :    sometimes backed by out-of-line generic functions.  The vectors are
      38              :    designed to interoperate with the GTY machinery.
      39              : 
      40              :    There are both 'index' and 'iterate' accessors.  The index accessor
      41              :    is implemented by operator[].  The iterator returns a boolean
      42              :    iteration condition and updates the iteration variable passed by
      43              :    reference.  Because the iterator will be inlined, the address-of
      44              :    can be optimized away.
      45              : 
      46              :    Each operation that increases the number of active elements is
      47              :    available in 'quick' and 'safe' variants.  The former presumes that
      48              :    there is sufficient allocated space for the operation to succeed
      49              :    (it dies if there is not).  The latter will reallocate the
      50              :    vector, if needed.  Reallocation causes an exponential increase in
      51              :    vector size.  If you know you will be adding N elements, it would
      52              :    be more efficient to use the reserve operation before adding the
      53              :    elements with the 'quick' operation.  This will ensure there are at
      54              :    least as many elements as you ask for, it will exponentially
      55              :    increase if there are too few spare slots.  If you want reserve a
      56              :    specific number of slots, but do not want the exponential increase
      57              :    (for instance, you know this is the last allocation), use the
      58              :    reserve_exact operation.  You can also create a vector of a
      59              :    specific size from the get go.
      60              : 
      61              :    You should prefer the push and pop operations, as they append and
      62              :    remove from the end of the vector. If you need to remove several
      63              :    items in one go, use the truncate operation.  The insert and remove
      64              :    operations allow you to change elements in the middle of the
      65              :    vector.  There are two remove operations, one which preserves the
      66              :    element ordering 'ordered_remove', and one which does not
      67              :    'unordered_remove'.  The latter function copies the end element
      68              :    into the removed slot, rather than invoke a memmove operation.  The
      69              :    'lower_bound' function will determine where to place an item in the
      70              :    array using insert that will maintain sorted order.
      71              : 
      72              :    Vectors are template types with three arguments: the type of the
      73              :    elements in the vector, the allocation strategy, and the physical
      74              :    layout to use
      75              : 
      76              :    Four allocation strategies are supported:
      77              : 
      78              :         - Heap: allocation is done using malloc/free.  This is the
      79              :           default allocation strategy.
      80              : 
      81              :         - GC: allocation is done using ggc_alloc/ggc_free.
      82              : 
      83              :         - GC atomic: same as GC with the exception that the elements
      84              :           themselves are assumed to be of an atomic type that does
      85              :           not need to be garbage collected.  This means that marking
      86              :           routines do not need to traverse the array marking the
      87              :           individual elements.  This increases the performance of
      88              :           GC activities.
      89              : 
      90              :    Two physical layouts are supported:
      91              : 
      92              :         - Embedded: The vector is structured using the trailing array
      93              :           idiom.  The last member of the structure is an array of size
      94              :           1.  When the vector is initially allocated, a single memory
      95              :           block is created to hold the vector's control data and the
      96              :           array of elements.  These vectors cannot grow without
      97              :           reallocation (see discussion on embeddable vectors below).
      98              : 
      99              :         - Space efficient: The vector is structured as a pointer to an
     100              :           embedded vector.  This is the default layout.  It means that
     101              :           vectors occupy a single word of storage before initial
     102              :           allocation.  Vectors are allowed to grow (the internal
     103              :           pointer is reallocated but the main vector instance does not
     104              :           need to relocate).
     105              : 
     106              :    The type, allocation and layout are specified when the vector is
     107              :    declared.
     108              : 
     109              :    If you need to directly manipulate a vector, then the 'address'
     110              :    accessor will return the address of the start of the vector.  Also
     111              :    the 'space' predicate will tell you whether there is spare capacity
     112              :    in the vector.  You will not normally need to use these two functions.
     113              : 
     114              :    Not all vector operations support non-POD types and such restrictions
     115              :    are enforced through static assertions.  Some operations which often use
     116              :    memmove to move elements around like quick_insert, safe_insert,
     117              :    ordered_remove, unordered_remove, block_remove etc. require trivially
     118              :    copyable types.  Sorting operations, qsort, sort and stablesort, require
     119              :    those too but as an extension allow also std::pair of 2 trivially copyable
     120              :    types which happens to work even when std::pair itself isn't trivially
     121              :    copyable.  The quick_grow and safe_grow operations require trivially
     122              :    default constructible types.  One can use quick_grow_cleared or
     123              :    safe_grow_cleared for non-trivially default constructible types if needed
     124              :    (but of course such operation is more expensive then).  The pop operation
     125              :    returns reference to the last element only for trivially destructible
     126              :    types, for non-trivially destructible types one should use last operation
     127              :    followed by pop which in that case returns void.
     128              :    And finally, the GC and GC atomic vectors should always be used with
     129              :    trivially destructible types, as nothing will invoke destructors when they
     130              :    are freed during GC.
     131              : 
     132              :    Notes on the different layout strategies
     133              : 
     134              :    * Embeddable vectors (vec<T, A, vl_embed>)
     135              : 
     136              :      These vectors are suitable to be embedded in other data
     137              :      structures so that they can be pre-allocated in a contiguous
     138              :      memory block.
     139              : 
     140              :      Embeddable vectors are implemented using the trailing array
     141              :      idiom, thus they are not resizeable without changing the address
     142              :      of the vector object itself.  This means you cannot have
     143              :      variables or fields of embeddable vector type -- always use a
     144              :      pointer to a vector.  The one exception is the final field of a
     145              :      structure, which could be a vector type.
     146              : 
     147              :      You will have to use the embedded_size & embedded_init calls to
     148              :      create such objects, and they will not be resizeable (so the
     149              :      'safe' allocation variants are not available).
     150              : 
     151              :      Properties of embeddable vectors:
     152              : 
     153              :           - The whole vector and control data are allocated in a single
     154              :             contiguous block.  It uses the trailing-vector idiom, so
     155              :             allocation must reserve enough space for all the elements
     156              :             in the vector plus its control data.
     157              :           - The vector cannot be re-allocated.
     158              :           - The vector cannot grow nor shrink.
     159              :           - No indirections needed for access/manipulation.
     160              :           - It requires 2 words of storage (prior to vector allocation).
     161              : 
     162              : 
     163              :    * Space efficient vector (vec<T, A, vl_ptr>)
     164              : 
     165              :      These vectors can grow dynamically and are allocated together
     166              :      with their control data.  They are suited to be included in data
     167              :      structures.  Prior to initial allocation, they only take a single
     168              :      word of storage.
     169              : 
     170              :      These vectors are implemented as a pointer to embeddable vectors.
     171              :      The semantics allow for this pointer to be NULL to represent
     172              :      empty vectors.  This way, empty vectors occupy minimal space in
     173              :      the structure containing them.
     174              : 
     175              :      Properties:
     176              : 
     177              :         - The whole vector and control data are allocated in a single
     178              :           contiguous block.
     179              :         - The whole vector may be re-allocated.
     180              :         - Vector data may grow and shrink.
     181              :         - Access and manipulation requires a pointer test and
     182              :           indirection.
     183              :         - It requires 1 word of storage (prior to vector allocation).
     184              : 
     185              :    An example of their use would be,
     186              : 
     187              :    struct my_struct {
     188              :      // A space-efficient vector of tree pointers in GC memory.
     189              :      vec<tree, va_gc, vl_ptr> v;
     190              :    };
     191              : 
     192              :    struct my_struct *s;
     193              : 
     194              :    if (s->v.length ()) { we have some contents }
     195              :    s->v.safe_push (decl); // append some decl onto the end
     196              :    for (ix = 0; s->v.iterate (ix, &elt); ix++)
     197              :      { do something with elt }
     198              : */
     199              : 
     200              : /* Support function for statistics.  */
     201              : extern void dump_vec_loc_statistics (void);
     202              : 
     203              : /* Hashtable mapping vec addresses to descriptors.  */
     204              : extern htab_t vec_mem_usage_hash;
     205              : 
     206              : /* Destruct N elements in DST.  */
     207              : 
     208              : template <typename T>
     209              : inline void
     210     46958775 : vec_destruct (T *dst, unsigned n)
     211              : {
     212    225604645 :   for ( ; n; ++dst, --n)
     213    178645870 :     dst->~T ();
     214     23192769 : }
     215              : 
     216              : /* Control data for vectors.  This contains the number of allocated
     217              :    and used slots inside a vector.  */
     218              : 
     219              : struct vec_prefix
     220              : {
     221              :   /* FIXME - These fields should be private, but we need to cater to
     222              :              compilers that have stricter notions of PODness for types.  */
     223              : 
     224              :   /* Memory allocation support routines in vec.cc.  */
     225              :   void register_overhead (void *, size_t, size_t CXX_MEM_STAT_INFO);
     226              :   void release_overhead (void *, size_t, size_t, bool CXX_MEM_STAT_INFO);
     227              :   static unsigned calculate_allocation (vec_prefix *, unsigned, bool);
     228              :   static unsigned calculate_allocation_1 (unsigned, unsigned);
     229              : 
     230              :   /* Note that vec_prefix should be a base class for vec, but we use
     231              :      offsetof() on vector fields of tree structures (e.g.,
     232              :      tree_binfo::base_binfos), and offsetof only supports base types.
     233              : 
     234              :      To compensate, we make vec_prefix a field inside vec and make
     235              :      vec a friend class of vec_prefix so it can access its fields.  */
     236              :   template <typename, typename, typename> friend struct vec;
     237              : 
     238              :   /* The allocator types also need access to our internals.  */
     239              :   friend struct va_gc;
     240              :   friend struct va_gc_atomic;
     241              :   friend struct va_heap;
     242              : 
     243              :   unsigned m_alloc : 31;
     244              :   unsigned m_using_auto_storage : 1;
     245              :   unsigned m_num;
     246              : };
     247              : 
     248              : /* Calculate the number of slots to reserve a vector, making sure that
     249              :    RESERVE slots are free.  If EXACT grow exactly, otherwise grow
     250              :    exponentially.  PFX is the control data for the vector.  */
     251              : 
     252              : inline unsigned
     253   5582950459 : vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve,
     254              :                                   bool exact)
     255              : {
     256   5582950459 :   if (exact)
     257    840504644 :     return (pfx ? pfx->m_num : 0) + reserve;
     258   4742445815 :   else if (!pfx)
     259   3746770045 :     return MAX (4, reserve);
     260    995675770 :   return calculate_allocation_1 (pfx->m_alloc, pfx->m_num + reserve);
     261              : }
     262              : 
     263              : template<typename, typename, typename> struct vec;
     264              : 
     265              : /* Valid vector layouts
     266              : 
     267              :    vl_embed     - Embeddable vector that uses the trailing array idiom.
     268              :    vl_ptr       - Space efficient vector that uses a pointer to an
     269              :                   embeddable vector.  */
     270              : struct vl_embed { };
     271              : struct vl_ptr { };
     272              : 
     273              : 
     274              : /* Types of supported allocations
     275              : 
     276              :    va_heap      - Allocation uses malloc/free.
     277              :    va_gc        - Allocation uses ggc_alloc.
     278              :    va_gc_atomic - Same as GC, but individual elements of the array
     279              :                   do not need to be marked during collection.  */
     280              : 
     281              : /* Allocator type for heap vectors.  */
     282              : struct va_heap
     283              : {
     284              :   /* Heap vectors are frequently regular instances, so use the vl_ptr
     285              :      layout for them.  */
     286              :   typedef vl_ptr default_layout;
     287              : 
     288              :   template<typename T>
     289              :   static void reserve (vec<T, va_heap, vl_embed> *&, unsigned, bool
     290              :                        CXX_MEM_STAT_INFO);
     291              : 
     292              :   template<typename T>
     293              :   static void release (vec<T, va_heap, vl_embed> *&);
     294              : };
     295              : 
     296              : 
     297              : /* Allocator for heap memory.  Ensure there are at least RESERVE free
     298              :    slots in V.  If EXACT is true, grow exactly, else grow
     299              :    exponentially.  As a special case, if the vector had not been
     300              :    allocated and RESERVE is 0, no vector will be created.  */
     301              : 
     302              : template<typename T>
     303              : inline void
     304   2411748084 : va_heap::reserve (vec<T, va_heap, vl_embed> *&v, unsigned reserve, bool exact
     305              :                   MEM_STAT_DECL)
     306              : {
     307   2411748084 :   size_t elt_size = sizeof (T);
     308              :   unsigned alloc
     309   2411748084 :     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
     310   2411748084 :   gcc_checking_assert (alloc);
     311              : 
     312              :   if (GATHER_STATISTICS && v)
     313              :     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
     314              :                                   v->allocated (), false);
     315              : 
     316   2411748084 :   size_t size = vec<T, va_heap, vl_embed>::embedded_size (alloc);
     317   2748445613 :   unsigned nelem = v ? v->length () : 0;
     318   2411748084 :   v = static_cast <vec<T, va_heap, vl_embed> *> (xrealloc (v, size));
     319   2411748084 :   v->embedded_init (alloc, nelem);
     320              : 
     321              :   if (GATHER_STATISTICS)
     322              :     v->m_vecpfx.register_overhead (v, alloc, elt_size PASS_MEM_STAT);
     323   2411748084 : }
     324              : 
     325              : 
     326              : #if GCC_VERSION >= 4007
     327              : #pragma GCC diagnostic push
     328              : #pragma GCC diagnostic ignored "-Wfree-nonheap-object"
     329              : #endif
     330              : 
     331              : /* Free the heap space allocated for vector V.  */
     332              : 
     333              : template<typename T>
     334              : void
     335   2056368231 : va_heap::release (vec<T, va_heap, vl_embed> *&v)
     336              : {
     337   2056368231 :   size_t elt_size = sizeof (T);
     338      2679024 :   if (v == NULL)
     339              :     return;
     340              : 
     341              :   if (!std::is_trivially_destructible <T>::value)
     342      1401328 :     vec_destruct (v->address (), v->length ());
     343              : 
     344              :   if (GATHER_STATISTICS)
     345              :     v->m_vecpfx.release_overhead (v, elt_size * v->allocated (),
     346              :                                   v->allocated (), true);
     347   2052169212 :   ::free (v);
     348   2022114009 :   v = NULL;
     349              : }
     350              : 
     351              : #if GCC_VERSION >= 4007
     352              : #pragma GCC diagnostic pop
     353              : #endif
     354              : 
     355              : /* Allocator type for GC vectors.  Notice that we need the structure
     356              :    declaration even if GC is not enabled.  */
     357              : 
     358              : struct va_gc
     359              : {
     360              :   /* Use vl_embed as the default layout for GC vectors.  Due to GTY
     361              :      limitations, GC vectors must always be pointers, so it is more
     362              :      efficient to use a pointer to the vl_embed layout, rather than
     363              :      using a pointer to a pointer as would be the case with vl_ptr.  */
     364              :   typedef vl_embed default_layout;
     365              : 
     366              :   template<typename T, typename A>
     367              :   static void reserve (vec<T, A, vl_embed> *&, unsigned, bool
     368              :                        CXX_MEM_STAT_INFO);
     369              : 
     370              :   template<typename T, typename A>
     371              :   static void release (vec<T, A, vl_embed> *&v);
     372              : };
     373              : 
     374              : 
     375              : /* Free GC memory used by V and reset V to NULL.  */
     376              : 
     377              : template<typename T, typename A>
     378              : inline void
     379    438322864 : va_gc::release (vec<T, A, vl_embed> *&v)
     380              : {
     381    434920249 :   if (v)
     382    101405299 :     ::ggc_free (v);
     383    321027206 :   v = NULL;
     384              : }
     385              : 
     386              : 
     387              : /* Allocator for GC memory.  Ensure there are at least RESERVE free
     388              :    slots in V.  If EXACT is true, grow exactly, else grow
     389              :    exponentially.  As a special case, if the vector had not been
     390              :    allocated and RESERVE is 0, no vector will be created.  */
     391              : 
     392              : template<typename T, typename A>
     393              : void
     394   3171202379 : va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
     395              :                 MEM_STAT_DECL)
     396              : {
     397              :   unsigned alloc
     398   3171202379 :     = vec_prefix::calculate_allocation (v ? &v->m_vecpfx : 0, reserve, exact);
     399   3171202379 :   if (!alloc)
     400              :     {
     401            0 :       ::ggc_free (v);
     402            0 :       v = NULL;
     403            0 :       return;
     404              :     }
     405              : 
     406              :   /* Calculate the amount of space we want.  */
     407   3171202379 :   size_t size = vec<T, A, vl_embed>::embedded_size (alloc);
     408              : 
     409              :   /* Ask the allocator how much space it will really give us.  */
     410   6342404758 :   size = ::ggc_round_alloc_size (size);
     411              : 
     412              :   /* Adjust the number of slots accordingly.  */
     413   3171202379 :   size_t vec_offset = sizeof (vec_prefix);
     414   3171202379 :   size_t elt_size = sizeof (T);
     415   3171202379 :   alloc = (size - vec_offset) / elt_size;
     416              : 
     417              :   /* And finally, recalculate the amount of space we ask for.  */
     418   3171202379 :   size = vec_offset + alloc * elt_size;
     419              : 
     420   3171202379 :   unsigned nelem = v ? v->length () : 0;
     421   3171202379 :   v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
     422              :                                                                PASS_MEM_STAT));
     423   3171202379 :   v->embedded_init (alloc, nelem);
     424              : }
     425              : 
     426              : 
     427              : /* Allocator type for GC vectors.  This is for vectors of types
     428              :    atomics w.r.t. collection, so allocation and deallocation is
     429              :    completely inherited from va_gc.  */
     430              : struct va_gc_atomic : va_gc
     431              : {
     432              : };
     433              : 
     434              : 
     435              : /* Generic vector template.  Default values for A and L indicate the
     436              :    most commonly used strategies.
     437              : 
     438              :    FIXME - Ideally, they would all be vl_ptr to encourage using regular
     439              :            instances for vectors, but the existing GTY machinery is limited
     440              :            in that it can only deal with GC objects that are pointers
     441              :            themselves.
     442              : 
     443              :            This means that vector operations that need to deal with
     444              :            potentially NULL pointers, must be provided as free
     445              :            functions (see the vec_safe_* functions above).  */
     446              : template<typename T,
     447              :          typename A = va_heap,
     448              :          typename L = typename A::default_layout>
     449              : struct GTY((user)) vec
     450              : {
     451              : };
     452              : 
     453              : /* Allow C++11 range-based 'for' to work directly on vec<T>*.  */
     454              : template<typename T, typename A, typename L>
     455    217571357 : T* begin (vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
     456              : template<typename T, typename A, typename L>
     457    217531970 : T* end (vec<T,A,L> *v) { return v ? v->end () : nullptr; }
     458              : template<typename T, typename A, typename L>
     459         6331 : const T* begin (const vec<T,A,L> *v) { return v ? v->begin () : nullptr; }
     460              : template<typename T, typename A, typename L>
     461      6390571 : const T* end (const vec<T,A,L> *v) { return v ? v->end () : nullptr; }
     462              : 
     463              : /* Generic vec<> debug helpers.
     464              : 
     465              :    These need to be instantiated for each vec<TYPE> used throughout
     466              :    the compiler like this:
     467              : 
     468              :     DEFINE_DEBUG_VEC (TYPE)
     469              : 
     470              :    The reason we have a debug_helper() is because GDB can't
     471              :    disambiguate a plain call to debug(some_vec), and it must be called
     472              :    like debug<TYPE>(some_vec).  */
     473              : 
     474              : template<typename T>
     475              : void
     476            0 : debug_helper (vec<T> &ref)
     477              : {
     478              :   unsigned i;
     479            0 :   for (i = 0; i < ref.length (); ++i)
     480              :     {
     481            0 :       fprintf (stderr, "[%d] = ", i);
     482            0 :       debug_slim (ref[i]);
     483            0 :       fputc ('\n', stderr);
     484              :     }
     485            0 : }
     486              : 
     487              : /* We need a separate va_gc variant here because default template
     488              :    argument for functions cannot be used in c++-98.  Once this
     489              :    restriction is removed, those variant should be folded with the
     490              :    above debug_helper.  */
     491              : 
     492              : template<typename T>
     493              : void
     494            0 : debug_helper (vec<T, va_gc> &ref)
     495              : {
     496              :   unsigned i;
     497            0 :   for (i = 0; i < ref.length (); ++i)
     498              :     {
     499            0 :       fprintf (stderr, "[%d] = ", i);
     500            0 :       debug_slim (ref[i]);
     501            0 :       fputc ('\n', stderr);
     502              :     }
     503            0 : }
     504              : 
     505              : /* Macro to define debug(vec<T>) and debug(vec<T, va_gc>) helper
     506              :    functions for a type T.  */
     507              : 
     508              : #define DEFINE_DEBUG_VEC(T) \
     509              :   template void debug_helper (vec<T> &);              \
     510              :   template void debug_helper (vec<T, va_gc> &);               \
     511              :   /* Define the vec<T> debug functions.  */               \
     512              :   DEBUG_FUNCTION void                                   \
     513              :   debug (vec<T> &ref)                                 \
     514              :   {                                                     \
     515              :     debug_helper <T> (ref);                               \
     516              :   }                                                     \
     517              :   DEBUG_FUNCTION void                                   \
     518              :   debug (vec<T> *ptr)                                     \
     519              :   {                                                     \
     520              :     if (ptr)                                            \
     521              :       debug (*ptr);                                     \
     522              :     else                                                \
     523              :       fprintf (stderr, "<nil>\n");                      \
     524              :   }                                                     \
     525              :   /* Define the vec<T, va_gc> debug functions.  */        \
     526              :   DEBUG_FUNCTION void                                   \
     527              :   debug (vec<T, va_gc> &ref)                          \
     528              :   {                                                     \
     529              :     debug_helper <T> (ref);                               \
     530              :   }                                                     \
     531              :   DEBUG_FUNCTION void                                   \
     532              :   debug (vec<T, va_gc> *ptr)                              \
     533              :   {                                                     \
     534              :     if (ptr)                                            \
     535              :       debug (*ptr);                                     \
     536              :     else                                                \
     537              :       fprintf (stderr, "<nil>\n");                      \
     538              :   }
     539              : 
     540              : /* Default-construct N elements in DST.  */
     541              : 
     542              : template <typename T>
     543              : inline void
     544    743276771 : vec_default_construct (T *dst, unsigned n)
     545              : {
     546  19853944768 :   for ( ; n; ++dst, --n)
     547  19110667997 :     ::new (static_cast<void*>(dst)) T ();
     548     32161595 : }
     549              : 
     550              : /* Copy-construct N elements in DST from *SRC.  */
     551              : 
     552              : template <typename T>
     553              : inline void
     554    242831463 : vec_copy_construct (T *dst, const T *src, unsigned n)
     555              : {
     556   1327402010 :   for ( ; n; ++dst, ++src, --n)
     557   1084570547 :     ::new (static_cast<void*>(dst)) T (*src);
     558     97708287 : }
     559              : 
     560              : /* Type to provide zero-initialized values for vec<T, A, L>.  This is
     561              :    used to  provide nil initializers for vec instances.  Since vec must
     562              :    be a trivially copyable type that can be copied by memcpy and zeroed
     563              :    out by memset, it must have defaulted default and copy ctor and copy
     564              :    assignment.  To initialize a vec either use value initialization
     565              :    (e.g., vec() or vec v{ };) or assign it the value vNULL.  This isn't
     566              :    needed for file-scope and function-local static vectors, which are
     567              :    zero-initialized by default.  */
     568              : struct vnull { };
     569              : constexpr vnull vNULL{ };
     570              : 
     571              : 
     572              : /* Embeddable vector.  These vectors are suitable to be embedded
     573              :    in other data structures so that they can be pre-allocated in a
     574              :    contiguous memory block.
     575              : 
     576              :    Embeddable vectors are implemented using the trailing array idiom,
     577              :    thus they are not resizeable without changing the address of the
     578              :    vector object itself.  This means you cannot have variables or
     579              :    fields of embeddable vector type -- always use a pointer to a
     580              :    vector.  The one exception is the final field of a structure, which
     581              :    could be a vector type.
     582              : 
     583              :    You will have to use the embedded_size & embedded_init calls to
     584              :    create such objects, and they will not be resizeable (so the 'safe'
     585              :    allocation variants are not available).
     586              : 
     587              :    Properties:
     588              : 
     589              :         - The whole vector and control data are allocated in a single
     590              :           contiguous block.  It uses the trailing-vector idiom, so
     591              :           allocation must reserve enough space for all the elements
     592              :           in the vector plus its control data.
     593              :         - The vector cannot be re-allocated.
     594              :         - The vector cannot grow nor shrink.
     595              :         - No indirections needed for access/manipulation.
     596              :         - It requires 2 words of storage (prior to vector allocation).  */
     597              : 
     598              : template<typename T, typename A>
     599              : struct GTY((user)) vec<T, A, vl_embed>
     600              : {
     601              : public:
     602   2070917940 :   unsigned allocated (void) const { return m_vecpfx.m_alloc; }
     603  29504434724 :   unsigned length (void) const { return m_vecpfx.m_num; }
     604  19457093148 :   bool is_empty (void) const { return m_vecpfx.m_num == 0; }
     605   6437589112 :   T *address (void) { return reinterpret_cast <T *> (this + 1); }
     606    325492562 :   const T *address (void) const
     607    325492562 :     { return reinterpret_cast <const T *> (this + 1); }
     608    194016333 :   T *begin () { return address (); }
     609    100921806 :   const T *begin () const { return address (); }
     610    268034861 :   T *end () { return address () + length (); }
     611    107306046 :   const T *end () const { return address () + length (); }
     612              :   const T &operator[] (unsigned) const;
     613              :   T &operator[] (unsigned);
     614              :   const T &last (void) const;
     615              :   T &last (void);
     616              :   bool space (unsigned) const;
     617              :   bool iterate (unsigned, T *) const;
     618              :   bool iterate (unsigned, T **) const;
     619              :   vec *copy (ALONE_CXX_MEM_STAT_INFO) const;
     620              :   void splice (const vec &);
     621              :   void splice (const vec *src);
     622              :   T *quick_push (const T &);
     623              :   using pop_ret_type
     624              :     = typename std::conditional <std::is_trivially_destructible <T>::value,
     625              :                                  T &, void>::type;
     626              :   pop_ret_type pop (void);
     627              :   void truncate (unsigned);
     628              :   void quick_insert (unsigned, const T &);
     629              :   void ordered_remove (unsigned);
     630              :   void unordered_remove (unsigned);
     631              :   void block_remove (unsigned, unsigned);
     632              :   void qsort (int (*) (const void *, const void *));
     633              :   void sort (int (*) (const void *, const void *, void *), void *);
     634              :   void stablesort (int (*) (const void *, const void *, void *), void *);
     635              :   T *bsearch (const void *key, int (*compar) (const void *, const void *));
     636              :   T *bsearch (const void *key,
     637              :               int (*compar)(const void *, const void *, void *), void *);
     638              :   unsigned lower_bound (const T &, bool (*) (const T &, const T &)) const;
     639              :   bool contains (const T &search) const;
     640              :   static size_t embedded_size (unsigned);
     641              :   void embedded_init (unsigned, unsigned = 0, unsigned = 0);
     642              :   void quick_grow (unsigned len);
     643              :   void quick_grow_cleared (unsigned len);
     644              : 
     645              :   /* vec class can access our internal data and functions.  */
     646              :   template <typename, typename, typename> friend struct vec;
     647              : 
     648              :   /* The allocator types also need access to our internals.  */
     649              :   friend struct va_gc;
     650              :   friend struct va_gc_atomic;
     651              :   friend struct va_heap;
     652              : 
     653              :   /* FIXME - This field should be private, but we need to cater to
     654              :              compilers that have stricter notions of PODness for types.  */
     655              :   /* Align m_vecpfx to simplify address ().  */
     656              :   alignas (T) alignas (vec_prefix) vec_prefix m_vecpfx;
     657              : };
     658              : 
     659              : 
     660              : /* Convenience wrapper functions to use when dealing with pointers to
     661              :    embedded vectors.  Some functionality for these vectors must be
     662              :    provided via free functions for these reasons:
     663              : 
     664              :         1- The pointer may be NULL (e.g., before initial allocation).
     665              : 
     666              :         2- When the vector needs to grow, it must be reallocated, so
     667              :            the pointer will change its value.
     668              : 
     669              :    Because of limitations with the current GC machinery, all vectors
     670              :    in GC memory *must* be pointers.  */
     671              : 
     672              : 
     673              : /* If V contains no room for NELEMS elements, return false. Otherwise,
     674              :    return true.  */
     675              : template<typename T, typename A>
     676              : inline bool
     677  57728581987 : vec_safe_space (const vec<T, A, vl_embed> *v, unsigned nelems)
     678              : {
     679  >11283*10^7 :   return v ? v->space (nelems) : nelems == 0;
     680              : }
     681              : 
     682              : 
     683              : /* If V is NULL, return 0.  Otherwise, return V->length().  */
     684              : template<typename T, typename A>
     685              : inline unsigned
     686  >29971*10^7 : vec_safe_length (const vec<T, A, vl_embed> *v)
     687              : {
     688  >29511*10^7 :   return v ? v->length () : 0;
     689              : }
     690              : 
     691              : 
     692              : /* If V is NULL, return NULL.  Otherwise, return V->address().  */
     693              : template<typename T, typename A>
     694              : inline T *
     695     69930662 : vec_safe_address (vec<T, A, vl_embed> *v)
     696              : {
     697     69930662 :   return v ? v->address () : NULL;
     698              : }
     699              : 
     700              : 
     701              : /* If V is NULL, return true.  Otherwise, return V->is_empty().  */
     702              : template<typename T, typename A>
     703              : inline bool
     704   3763654478 : vec_safe_is_empty (vec<T, A, vl_embed> *v)
     705              : {
     706   3763600635 :   return v ? v->is_empty () : true;
     707              : }
     708              : 
     709              : /* If V does not have space for NELEMS elements, call
     710              :    V->reserve(NELEMS, EXACT).  */
     711              : template<typename T, typename A>
     712              : inline bool
     713  57757104915 : vec_safe_reserve (vec<T, A, vl_embed> *&v, unsigned nelems, bool exact = false
     714              :                   CXX_MEM_STAT_INFO)
     715              : {
     716  >11286*10^7 :   bool extend = nelems ? !vec_safe_space (v, nelems) : false;
     717              :   if (extend)
     718   3317289539 :     A::reserve (v, nelems, exact PASS_MEM_STAT);
     719  57757104915 :   return extend;
     720              : }
     721              : 
     722              : template<typename T, typename A>
     723              : inline bool
     724    399502609 : vec_safe_reserve_exact (vec<T, A, vl_embed> *&v, unsigned nelems
     725              :                         CXX_MEM_STAT_INFO)
     726              : {
     727     76709753 :   return vec_safe_reserve (v, nelems, true PASS_MEM_STAT);
     728              : }
     729              : 
     730              : 
     731              : /* Allocate GC memory for V with space for NELEMS slots.  If NELEMS
     732              :    is 0, V is initialized to NULL.  */
     733              : 
     734              : template<typename T, typename A>
     735              : inline void
     736    392613460 : vec_alloc (vec<T, A, vl_embed> *&v, unsigned nelems CXX_MEM_STAT_INFO)
     737              : {
     738    163207889 :   v = NULL;
     739    392317230 :   vec_safe_reserve (v, nelems, false PASS_MEM_STAT);
     740      3580513 : }
     741              : 
     742              : 
     743              : /* Free the GC memory allocated by vector V and set it to NULL.  */
     744              : 
     745              : template<typename T, typename A>
     746              : inline void
     747    421515966 : vec_free (vec<T, A, vl_embed> *&v)
     748              : {
     749    438664688 :   A::release (v);
     750     24576341 : }
     751              : 
     752              : 
     753              : /* Grow V to length LEN.  Allocate it, if necessary.  */
     754              : template<typename T, typename A>
     755              : inline void
     756      3022382 : vec_safe_grow (vec<T, A, vl_embed> *&v, unsigned len,
     757              :                bool exact = false CXX_MEM_STAT_INFO)
     758              : {
     759      3022382 :   unsigned oldlen = vec_safe_length (v);
     760       589515 :   gcc_checking_assert (len >= oldlen);
     761      3022382 :   vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
     762      3022382 :   v->quick_grow (len);
     763      3022382 : }
     764              : 
     765              : 
     766              : /* If V is NULL, allocate it.  Call V->safe_grow_cleared(LEN).  */
     767              : template<typename T, typename A>
     768              : inline void
     769     78585865 : vec_safe_grow_cleared (vec<T, A, vl_embed> *&v, unsigned len,
     770              :                        bool exact = false CXX_MEM_STAT_INFO)
     771              : {
     772     78585865 :   unsigned oldlen = vec_safe_length (v);
     773     47542213 :   gcc_checking_assert (len >= oldlen);
     774     78585865 :   vec_safe_reserve (v, len - oldlen, exact PASS_MEM_STAT);
     775     78585865 :   v->quick_grow_cleared (len);
     776     78585865 : }
     777              : 
     778              : 
     779              : /* Assume V is not NULL.  */
     780              : 
     781              : template<typename T>
     782              : inline void
     783     14069294 : vec_safe_grow_cleared (vec<T, va_heap, vl_ptr> *&v,
     784              :                        unsigned len, bool exact = false CXX_MEM_STAT_INFO)
     785              : {
     786     14069294 :   v->safe_grow_cleared (len, exact PASS_MEM_STAT);
     787     14069294 : }
     788              : 
     789              : /* If V does not have space for NELEMS elements, call
     790              :    V->reserve(NELEMS, EXACT).  */
     791              : 
     792              : template<typename T>
     793              : inline bool
     794              : vec_safe_reserve (vec<T, va_heap, vl_ptr> *&v, unsigned nelems, bool exact = false
     795              :                   CXX_MEM_STAT_INFO)
     796              : {
     797              :   return v->reserve (nelems, exact);
     798              : }
     799              : 
     800              : 
     801              : /* If V is NULL return false, otherwise return V->iterate(IX, PTR).  */
     802              : template<typename T, typename A>
     803              : inline bool
     804  40137657784 : vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T **ptr)
     805              : {
     806  39940476205 :   if (v)
     807  >15106*10^7 :     return v->iterate (ix, ptr);
     808              :   else
     809              :     {
     810              :       *ptr = 0;
     811              :       return false;
     812              :     }
     813              : }
     814              : 
     815              : template<typename T, typename A>
     816              : inline bool
     817  21257803286 : vec_safe_iterate (const vec<T, A, vl_embed> *v, unsigned ix, T *ptr)
     818              : {
     819  21209444277 :   if (v)
     820   3796779465 :     return v->iterate (ix, ptr);
     821              :   else
     822              :     {
     823       240731 :       *ptr = 0;
     824       240731 :       return false;
     825              :     }
     826              : }
     827              : 
     828              : 
     829              : /* If V has no room for one more element, reallocate it.  Then call
     830              :    V->quick_push(OBJ).  */
     831              : template<typename T, typename A>
     832              : inline T *
     833  54126701651 : vec_safe_push (vec<T, A, vl_embed> *&v, const T &obj CXX_MEM_STAT_INFO)
     834              : {
     835  54126701651 :   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
     836  54126701651 :   return v->quick_push (obj);
     837              : }
     838              : 
     839              : 
     840              : /* if V has no room for one more element, reallocate it.  Then call
     841              :    V->quick_insert(IX, OBJ).  */
     842              : template<typename T, typename A>
     843              : inline void
     844     22753657 : vec_safe_insert (vec<T, A, vl_embed> *&v, unsigned ix, const T &obj
     845              :                  CXX_MEM_STAT_INFO)
     846              : {
     847     22753657 :   vec_safe_reserve (v, 1, false PASS_MEM_STAT);
     848     22753657 :   v->quick_insert (ix, obj);
     849     22753657 : }
     850              : 
     851              : 
     852              : /* If V is NULL, do nothing.  Otherwise, call V->truncate(SIZE).  */
     853              : template<typename T, typename A>
     854              : inline void
     855   1671780225 : vec_safe_truncate (vec<T, A, vl_embed> *v, unsigned size)
     856              : {
     857   1671777648 :   if (v)
     858   1330403083 :     v->truncate (size);
     859         2569 : }
     860              : 
     861              : 
     862              : /* If SRC is not NULL, return a pointer to a copy of it.  */
     863              : template<typename T, typename A>
     864              : inline vec<T, A, vl_embed> *
     865    137627899 : vec_safe_copy (vec<T, A, vl_embed> *src CXX_MEM_STAT_INFO)
     866              : {
     867    135010000 :   return src ? src->copy (ALONE_PASS_MEM_STAT) : NULL;
     868              : }
     869              : 
     870              : /* Copy the elements from SRC to the end of DST as if by memcpy.
     871              :    Reallocate DST, if necessary.  */
     872              : template<typename T, typename A>
     873              : inline void
     874    629848945 : vec_safe_splice (vec<T, A, vl_embed> *&dst, const vec<T, A, vl_embed> *src
     875              :                  CXX_MEM_STAT_INFO)
     876              : {
     877   1030111107 :   unsigned src_len = vec_safe_length (src);
     878    400262162 :   if (src_len)
     879              :     {
     880     18682607 :       vec_safe_reserve_exact (dst, vec_safe_length (dst) + src_len
     881              :                               PASS_MEM_STAT);
     882     10658923 :       dst->splice (*src);
     883              :     }
     884    629848945 : }
     885              : 
     886              : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
     887              :    size of the vector and so should be used with care.  */
     888              : 
     889              : template<typename T, typename A>
     890              : inline bool
     891      7612824 : vec_safe_contains (vec<T, A, vl_embed> *v, const T &search)
     892              : {
     893      7639104 :   return v ? v->contains (search) : false;
     894              : }
     895              : 
     896              : /* Index into vector.  Return the IX'th element.  IX must be in the
     897              :    domain of the vector.  */
     898              : 
     899              : template<typename T, typename A>
     900              : inline const T &
     901    859720985 : vec<T, A, vl_embed>::operator[] (unsigned ix) const
     902              : {
     903    859720985 :   gcc_checking_assert (ix < m_vecpfx.m_num);
     904    859720985 :   return address ()[ix];
     905              : }
     906              : 
     907              : template<typename T, typename A>
     908              : inline T &
     909  >41578*10^7 : vec<T, A, vl_embed>::operator[] (unsigned ix)
     910              : {
     911  >41578*10^7 :   gcc_checking_assert (ix < m_vecpfx.m_num);
     912  >41578*10^7 :   return address ()[ix];
     913              : }
     914              : 
     915              : 
     916              : /* Get the final element of the vector, which must not be empty.  */
     917              : 
     918              : template<typename T, typename A>
     919              : inline const T &
     920              : vec<T, A, vl_embed>::last (void) const
     921              : {
     922              :   gcc_checking_assert (m_vecpfx.m_num > 0);
     923              :   return (*this)[m_vecpfx.m_num - 1];
     924              : }
     925              : 
     926              : template<typename T, typename A>
     927              : inline T &
     928  33544960114 : vec<T, A, vl_embed>::last (void)
     929              : {
     930  33544960114 :   gcc_checking_assert (m_vecpfx.m_num > 0);
     931  33544960114 :   return (*this)[m_vecpfx.m_num - 1];
     932              : }
     933              : 
     934              : 
     935              : /* If this vector has space for NELEMS additional entries, return
     936              :    true.  You usually only need to use this if you are doing your
     937              :    own vector reallocation, for instance on an embedded vector.  This
     938              :    returns true in exactly the same circumstances that vec::reserve
     939              :    will.  */
     940              : 
     941              : template<typename T, typename A>
     942              : inline bool
     943  >23700*10^7 : vec<T, A, vl_embed>::space (unsigned nelems) const
     944              : {
     945  >11391*10^7 :   return m_vecpfx.m_alloc - m_vecpfx.m_num >= nelems;
     946              : }
     947              : 
     948              : 
     949              : /* Return iteration condition and update *PTR to (a copy of) the IX'th
     950              :    element of this vector.  Use this to iterate over the elements of a
     951              :    vector as follows,
     952              : 
     953              :      for (ix = 0; v->iterate (ix, &val); ix++)
     954              :        continue;  */
     955              : 
     956              : template<typename T, typename A>
     957              : inline bool
     958  >10334*10^7 : vec<T, A, vl_embed>::iterate (unsigned ix, T *ptr) const
     959              : {
     960  73993166648 :   if (ix < m_vecpfx.m_num)
     961              :     {
     962  52124006795 :       *ptr = address ()[ix];
     963     61662678 :       return true;
     964              :     }
     965              :   else
     966              :     {
     967     44944373 :       *ptr = 0;
     968     44944373 :       return false;
     969              :     }
     970              : }
     971              : 
     972              : 
     973              : /* Return iteration condition and update *PTR to point to the
     974              :    IX'th element of this vector.  Use this to iterate over the
     975              :    elements of a vector as follows,
     976              : 
     977              :      for (ix = 0; v->iterate (ix, &ptr); ix++)
     978              :        continue;
     979              : 
     980              :    This variant is for vectors of objects.  */
     981              : 
     982              : template<typename T, typename A>
     983              : inline bool
     984  35866725569 : vec<T, A, vl_embed>::iterate (unsigned ix, T **ptr) const
     985              : {
     986  35075955381 :   if (ix < m_vecpfx.m_num)
     987              :     {
     988  28141941158 :       *ptr = const_cast<T *> (&address ()[ix]);
     989     63193650 :       return true;
     990              :     }
     991              :   else
     992              :     {
     993       358838 :       *ptr = 0;
     994       358838 :       return false;
     995              :     }
     996              : }
     997              : 
     998              : 
     999              : /* Return a pointer to a copy of this vector.  */
    1000              : 
    1001              : template<typename T, typename A>
    1002              : inline vec<T, A, vl_embed> *
    1003    194679880 : vec<T, A, vl_embed>::copy (ALONE_MEM_STAT_DECL) const
    1004              : {
    1005    194679880 :   vec<T, A, vl_embed> *new_vec = NULL;
    1006    194679880 :   unsigned len = length ();
    1007    194679880 :   if (len)
    1008              :     {
    1009    194040951 :       vec_alloc (new_vec, len PASS_MEM_STAT);
    1010    194040951 :       new_vec->embedded_init (len, len);
    1011    292027051 :       vec_copy_construct (new_vec->address (), address (), len);
    1012              :     }
    1013    194679880 :   return new_vec;
    1014              : }
    1015              : 
    1016              : 
    1017              : /* Copy the elements from SRC to the end of this vector as if by memcpy.
    1018              :    The vector must have sufficient headroom available.  */
    1019              : 
    1020              : template<typename T, typename A>
    1021              : inline void
    1022     24142922 : vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> &src)
    1023              : {
    1024     24142922 :   unsigned len = src.length ();
    1025     24142922 :   if (len)
    1026              :     {
    1027     24142922 :       gcc_checking_assert (space (len));
    1028     24142922 :       vec_copy_construct (end (), src.address (), len);
    1029     24142922 :       m_vecpfx.m_num += len;
    1030              :     }
    1031     24142922 : }
    1032              : 
    1033              : template<typename T, typename A>
    1034              : inline void
    1035              : vec<T, A, vl_embed>::splice (const vec<T, A, vl_embed> *src)
    1036              : {
    1037              :   if (src)
    1038              :     splice (*src);
    1039              : }
    1040              : 
    1041              : 
    1042              : /* Push OBJ (a new element) onto the end of the vector.  There must be
    1043              :    sufficient space in the vector.  Return a pointer to the slot
    1044              :    where OBJ was inserted.  */
    1045              : 
    1046              : template<typename T, typename A>
    1047              : inline T *
    1048  >12287*10^7 : vec<T, A, vl_embed>::quick_push (const T &obj)
    1049              : {
    1050  >12287*10^7 :   gcc_checking_assert (space (1));
    1051  >12287*10^7 :   T *slot = &address ()[m_vecpfx.m_num++];
    1052  >12287*10^7 :   ::new (static_cast<void*>(slot)) T (obj);
    1053  >12287*10^7 :   return slot;
    1054              : }
    1055              : 
    1056              : 
    1057              : /* Pop and return a reference to the last element off the end of the
    1058              :    vector.  If T has non-trivial destructor, this method just pops
    1059              :    the element and returns void type.  */
    1060              : 
    1061              : template<typename T, typename A>
    1062              : inline typename vec<T, A, vl_embed>::pop_ret_type
    1063  74578022923 : vec<T, A, vl_embed>::pop (void)
    1064              : {
    1065  74578022923 :   gcc_checking_assert (length () > 0);
    1066  74578022923 :   T &last = address ()[--m_vecpfx.m_num];
    1067              :   if (!std::is_trivially_destructible <T>::value)
    1068              :     last.~T ();
    1069  74578022923 :   return static_cast <pop_ret_type> (last);
    1070              : }
    1071              : 
    1072              : 
    1073              : /* Set the length of the vector to SIZE.  The new length must be less
    1074              :    than or equal to the current length.  This is an O(1) operation.  */
    1075              : 
    1076              : template<typename T, typename A>
    1077              : inline void
    1078  54541121949 : vec<T, A, vl_embed>::truncate (unsigned size)
    1079              : {
    1080  54541121949 :   unsigned l = length ();
    1081  54541121949 :   gcc_checking_assert (l >= size);
    1082              :   if (!std::is_trivially_destructible <T>::value)
    1083     45557591 :     vec_destruct (address () + size, l - size);
    1084  54541121949 :   m_vecpfx.m_num = size;
    1085  54541121949 : }
    1086              : 
    1087              : 
    1088              : /* Insert an element, OBJ, at the IXth position of this vector.  There
    1089              :    must be sufficient space.  This operation is not suitable for non-trivially
    1090              :    copyable types.  */
    1091              : 
    1092              : template<typename T, typename A>
    1093              : inline void
    1094    628391702 : vec<T, A, vl_embed>::quick_insert (unsigned ix, const T &obj)
    1095              : {
    1096    628391702 :   gcc_checking_assert (length () < allocated ());
    1097    628391702 :   gcc_checking_assert (ix <= length ());
    1098              : #if GCC_VERSION >= 5000
    1099              :   /* GCC 4.8 and 4.9 only implement std::is_trivially_destructible,
    1100              :      but not std::is_trivially_copyable nor
    1101              :      std::is_trivially_default_constructible.  */
    1102              :   static_assert (std::is_trivially_copyable <T>::value, "");
    1103              : #endif
    1104    628391702 :   T *slot = &address ()[ix];
    1105    628391702 :   memmove (slot + 1, slot, (m_vecpfx.m_num++ - ix) * sizeof (T));
    1106    628391702 :   *slot = obj;
    1107    628391702 : }
    1108              : 
    1109              : 
    1110              : /* Remove an element from the IXth position of this vector.  Ordering of
    1111              :    remaining elements is preserved.  This is an O(N) operation due to
    1112              :    memmove.  Not suitable for non-trivially copyable types.  */
    1113              : 
    1114              : template<typename T, typename A>
    1115              : inline void
    1116     54782750 : vec<T, A, vl_embed>::ordered_remove (unsigned ix)
    1117              : {
    1118     54782750 :   gcc_checking_assert (ix < length ());
    1119              : #if GCC_VERSION >= 5000
    1120              :   static_assert (std::is_trivially_copyable <T>::value, "");
    1121              : #endif
    1122     54782750 :   T *slot = &address ()[ix];
    1123     54782750 :   memmove (slot, slot + 1, (--m_vecpfx.m_num - ix) * sizeof (T));
    1124     54782750 : }
    1125              : 
    1126              : 
    1127              : /* Remove elements in [START, END) from VEC for which COND holds.  Ordering of
    1128              :    remaining elements is preserved.  This is an O(N) operation.  */
    1129              : 
    1130              : #define VEC_ORDERED_REMOVE_IF_FROM_TO(vec, read_index, write_index,     \
    1131              :                                       elem_ptr, start, end, cond)       \
    1132              :   {                                                                     \
    1133              :     gcc_assert ((end) <= (vec).length ());                           \
    1134              :     for (read_index = write_index = (start); read_index < (end);     \
    1135              :          ++read_index)                                                  \
    1136              :       {                                                                 \
    1137              :         elem_ptr = &(vec)[read_index];                                      \
    1138              :         bool remove_p = (cond);                                         \
    1139              :         if (remove_p)                                                   \
    1140              :           continue;                                                     \
    1141              :                                                                         \
    1142              :         if (read_index != write_index)                                  \
    1143              :           (vec)[write_index] = (vec)[read_index];                       \
    1144              :                                                                         \
    1145              :         write_index++;                                                  \
    1146              :       }                                                                 \
    1147              :                                                                         \
    1148              :     if (read_index - write_index > 0)                                        \
    1149              :       (vec).block_remove (write_index, read_index - write_index);       \
    1150              :   }
    1151              : 
    1152              : 
    1153              : /* Remove elements from VEC for which COND holds.  Ordering of remaining
    1154              :    elements is preserved.  This is an O(N) operation.  */
    1155              : 
    1156              : #define VEC_ORDERED_REMOVE_IF(vec, read_index, write_index, elem_ptr,   \
    1157              :                               cond)                                     \
    1158              :   VEC_ORDERED_REMOVE_IF_FROM_TO ((vec), read_index, write_index,        \
    1159              :                                  elem_ptr, 0, (vec).length (), (cond))
    1160              : 
    1161              : /* Remove an element from the IXth position of this vector.  Ordering of
    1162              :    remaining elements is destroyed.  This is an O(1) operation.  */
    1163              : 
    1164              : template<typename T, typename A>
    1165              : inline void
    1166    298416362 : vec<T, A, vl_embed>::unordered_remove (unsigned ix)
    1167              : {
    1168    298416362 :   gcc_checking_assert (ix < length ());
    1169              : #if GCC_VERSION >= 5000
    1170              :   static_assert (std::is_trivially_copyable <T>::value, "");
    1171              : #endif
    1172    298416362 :   T *p = address ();
    1173    298416362 :   p[ix] = p[--m_vecpfx.m_num];
    1174    298416362 : }
    1175              : 
    1176              : 
    1177              : /* Remove LEN elements starting at the IXth.  Ordering is retained.
    1178              :    This is an O(N) operation due to memmove.  */
    1179              : 
    1180              : template<typename T, typename A>
    1181              : inline void
    1182       905825 : vec<T, A, vl_embed>::block_remove (unsigned ix, unsigned len)
    1183              : {
    1184       905825 :   gcc_checking_assert (ix + len <= length ());
    1185              : #if GCC_VERSION >= 5000
    1186              :   static_assert (std::is_trivially_copyable <T>::value, "");
    1187              : #endif
    1188       905825 :   T *slot = &address ()[ix];
    1189       905825 :   m_vecpfx.m_num -= len;
    1190       905825 :   memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
    1191       905825 : }
    1192              : 
    1193              : 
    1194              : #if GCC_VERSION >= 5000
    1195              : namespace vec_detail
    1196              : {
    1197              :   /* gcc_{qsort,qsort_r,stablesort_r} implementation under the hood
    1198              :      uses memcpy/memmove to reorder the array elements.
    1199              :      We want to assert these methods aren't used on types for which
    1200              :      that isn't appropriate, but unfortunately std::pair of 2 trivially
    1201              :      copyable types isn't trivially copyable and we use qsort on many
    1202              :      such std::pair instantiations.  Let's allow both trivially
    1203              :      copyable types and std::pair of 2 trivially copyable types as
    1204              :      exception for qsort/sort/stablesort.  */
    1205              :   template<typename T>
    1206              :   struct is_trivially_copyable_or_pair : std::is_trivially_copyable<T> { };
    1207              : 
    1208              :   template<typename T, typename U>
    1209              :   struct is_trivially_copyable_or_pair<std::pair<T, U> >
    1210              :   : std::integral_constant<bool, std::is_trivially_copyable<T>::value
    1211              :     && std::is_trivially_copyable<U>::value> { };
    1212              : }
    1213              : #endif
    1214              : 
    1215              : /* Sort the contents of this vector with qsort.  CMP is the comparison
    1216              :    function to pass to qsort.  */
    1217              : 
    1218              : template<typename T, typename A>
    1219              : inline void
    1220    124344833 : vec<T, A, vl_embed>::qsort (int (*cmp) (const void *, const void *))
    1221              : {
    1222              : #if GCC_VERSION >= 5000
    1223              :   static_assert (vec_detail::is_trivially_copyable_or_pair <T>::value, "");
    1224              : #endif
    1225    124344833 :   if (length () > 1)
    1226    107064058 :     gcc_qsort (address (), length (), sizeof (T), cmp);
    1227    124344833 : }
    1228              : 
    1229              : /* Sort the contents of this vector with qsort.  CMP is the comparison
    1230              :    function to pass to qsort.  */
    1231              : 
    1232              : template<typename T, typename A>
    1233              : inline void
    1234      1617288 : vec<T, A, vl_embed>::sort (int (*cmp) (const void *, const void *, void *),
    1235              :                            void *data)
    1236              : {
    1237              : #if GCC_VERSION >= 5000
    1238              :   static_assert (vec_detail::is_trivially_copyable_or_pair <T>::value, "");
    1239              : #endif
    1240      1617288 :   if (length () > 1)
    1241      1601994 :     gcc_sort_r (address (), length (), sizeof (T), cmp, data);
    1242      1617288 : }
    1243              : 
    1244              : /* Sort the contents of this vector with gcc_stablesort_r.  CMP is the
    1245              :    comparison function to pass to qsort.  */
    1246              : 
    1247              : template<typename T, typename A>
    1248              : inline void
    1249         7092 : vec<T, A, vl_embed>::stablesort (int (*cmp) (const void *, const void *,
    1250              :                                              void *), void *data)
    1251              : {
    1252              : #if GCC_VERSION >= 5000
    1253              :   static_assert (vec_detail::is_trivially_copyable_or_pair <T>::value, "");
    1254              : #endif
    1255         7092 :   if (length () > 1)
    1256         6752 :     gcc_stablesort_r (address (), length (), sizeof (T), cmp, data);
    1257         7092 : }
    1258              : 
    1259              : /* Search the contents of the sorted vector with a binary search.
    1260              :    CMP is the comparison function to pass to bsearch.  */
    1261              : 
    1262              : template<typename T, typename A>
    1263              : inline T *
    1264        26674 : vec<T, A, vl_embed>::bsearch (const void *key,
    1265              :                               int (*compar) (const void *, const void *))
    1266              : {
    1267        26674 :   const void *base = this->address ();
    1268        26674 :   size_t nmemb = this->length ();
    1269        26674 :   size_t size = sizeof (T);
    1270              :   /* The following is a copy of glibc stdlib-bsearch.h.  */
    1271              :   size_t l, u, idx;
    1272              :   const void *p;
    1273              :   int comparison;
    1274              : 
    1275        26674 :   l = 0;
    1276        26674 :   u = nmemb;
    1277       104392 :   while (l < u)
    1278              :     {
    1279        97056 :       idx = (l + u) / 2;
    1280        97056 :       p = (const void *) (((const char *) base) + (idx * size));
    1281        97056 :       comparison = (*compar) (key, p);
    1282        97056 :       if (comparison < 0)
    1283              :         u = idx;
    1284        54728 :       else if (comparison > 0)
    1285              :         l = idx + 1;
    1286              :       else
    1287              :         return (T *)const_cast<void *>(p);
    1288              :     }
    1289              : 
    1290              :   return NULL;
    1291              : }
    1292              : 
    1293              : /* Search the contents of the sorted vector with a binary search.
    1294              :    CMP is the comparison function to pass to bsearch.  */
    1295              : 
    1296              : template<typename T, typename A>
    1297              : inline T *
    1298       199368 : vec<T, A, vl_embed>::bsearch (const void *key,
    1299              :                               int (*compar) (const void *, const void *,
    1300              :                                              void *), void *data)
    1301              : {
    1302       199368 :   const void *base = this->address ();
    1303       199368 :   size_t nmemb = this->length ();
    1304       199368 :   size_t size = sizeof (T);
    1305              :   /* The following is a copy of glibc stdlib-bsearch.h.  */
    1306              :   size_t l, u, idx;
    1307              :   const void *p;
    1308              :   int comparison;
    1309              : 
    1310       199368 :   l = 0;
    1311       199368 :   u = nmemb;
    1312       259888 :   while (l < u)
    1313              :     {
    1314       259888 :       idx = (l + u) / 2;
    1315       259888 :       p = (const void *) (((const char *) base) + (idx * size));
    1316       259888 :       comparison = (*compar) (key, p, data);
    1317       259888 :       if (comparison < 0)
    1318              :         u = idx;
    1319       221306 :       else if (comparison > 0)
    1320        21938 :         l = idx + 1;
    1321              :       else
    1322              :         return (T *)const_cast<void *>(p);
    1323              :     }
    1324              : 
    1325              :   return NULL;
    1326              : }
    1327              : 
    1328              : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
    1329              :    size of the vector and so should be used with care.  */
    1330              : 
    1331              : template<typename T, typename A>
    1332              : inline bool
    1333     52533058 : vec<T, A, vl_embed>::contains (const T &search) const
    1334              : {
    1335     52533058 :   unsigned int len = length ();
    1336     52533058 :   const T *p = address ();
    1337    171567944 :   for (unsigned int i = 0; i < len; i++)
    1338              :     {
    1339    134548159 :       const T *slot = &p[i];
    1340    134548159 :       if (*slot == search)
    1341              :         return true;
    1342              :     }
    1343              : 
    1344              :   return false;
    1345              : }
    1346              : 
    1347              : /* Find and return the first position in which OBJ could be inserted
    1348              :    without changing the ordering of this vector.  LESSTHAN is a
    1349              :    function that returns true if the first argument is strictly less
    1350              :    than the second.  */
    1351              : 
    1352              : template<typename T, typename A>
    1353              : unsigned
    1354     88751557 : vec<T, A, vl_embed>::lower_bound (const T &obj,
    1355              :                                   bool (*lessthan)(const T &, const T &))
    1356              :   const
    1357              : {
    1358     88751557 :   unsigned int len = length ();
    1359              :   unsigned int half, middle;
    1360     88751557 :   unsigned int first = 0;
    1361    208455362 :   while (len > 0)
    1362              :     {
    1363    119703805 :       half = len / 2;
    1364    119703805 :       middle = first;
    1365    119703805 :       middle += half;
    1366    119703805 :       const T &middle_elem = address ()[middle];
    1367    119703805 :       if (lessthan (middle_elem, obj))
    1368              :         {
    1369    101105467 :           first = middle;
    1370    101105467 :           ++first;
    1371    101105467 :           len = len - half - 1;
    1372              :         }
    1373              :       else
    1374              :         len = half;
    1375              :     }
    1376     88751557 :   return first;
    1377              : }
    1378              : 
    1379              : 
    1380              : /* Return the number of bytes needed to embed an instance of an
    1381              :    embeddable vec inside another data structure.
    1382              : 
    1383              :    Use these methods to determine the required size and initialization
    1384              :    of a vector V of type T embedded within another structure (as the
    1385              :    final member):
    1386              : 
    1387              :    size_t vec<T, A, vl_embed>::embedded_size (unsigned alloc);
    1388              :    void v->embedded_init (unsigned alloc, unsigned num);
    1389              : 
    1390              :    These allow the caller to perform the memory allocation.  */
    1391              : 
    1392              : template<typename T, typename A>
    1393              : inline size_t
    1394   5740664797 : vec<T, A, vl_embed>::embedded_size (unsigned alloc)
    1395              : {
    1396              :   struct alignas (T) U { char data[sizeof (T)]; };
    1397              :   typedef vec<U, A, vl_embed> vec_embedded;
    1398              :   typedef typename std::conditional<std::is_standard_layout<T>::value,
    1399              :                                     vec, vec_embedded>::type vec_stdlayout;
    1400              :   static_assert (sizeof (vec_stdlayout) == sizeof (vec), "");
    1401              :   static_assert (alignof (vec_stdlayout) == alignof (vec), "");
    1402   5740664797 :   return sizeof (vec_stdlayout) + alloc * sizeof (T);
    1403              : }
    1404              : 
    1405              : 
    1406              : /* Initialize the vector to contain room for ALLOC elements and
    1407              :    NUM active elements.  */
    1408              : 
    1409              : template<typename T, typename A>
    1410              : inline void
    1411  27794386885 : vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num, unsigned aut)
    1412              : {
    1413  27794386885 :   m_vecpfx.m_alloc = alloc;
    1414  27794386885 :   m_vecpfx.m_using_auto_storage = aut;
    1415  24368129331 :   m_vecpfx.m_num = num;
    1416   3215640370 : }
    1417              : 
    1418              : 
    1419              : /* Grow the vector to a specific length.  LEN must be as long or longer than
    1420              :    the current length.  The new elements are uninitialized.  */
    1421              : 
    1422              : template<typename T, typename A>
    1423              : inline void
    1424    261485529 : vec<T, A, vl_embed>::quick_grow (unsigned len)
    1425              : {
    1426    261485529 :   gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
    1427              : #if GCC_VERSION >= 5000
    1428              :   static_assert (std::is_trivially_default_constructible <T>::value, "");
    1429              : #endif
    1430    261485529 :   m_vecpfx.m_num = len;
    1431    261485529 : }
    1432              : 
    1433              : 
    1434              : /* Grow the vector to a specific length.  LEN must be as long or longer than
    1435              :    the current length.  The new elements are initialized to zero.  */
    1436              : 
    1437              : template<typename T, typename A>
    1438              : inline void
    1439    764211201 : vec<T, A, vl_embed>::quick_grow_cleared (unsigned len)
    1440              : {
    1441    764211201 :   unsigned oldlen = length ();
    1442    764211201 :   size_t growby = len - oldlen;
    1443    764211201 :   gcc_checking_assert (length () <= len && len <= m_vecpfx.m_alloc);
    1444    764211201 :   m_vecpfx.m_num = len;
    1445    764211201 :   if (growby != 0)
    1446    743276771 :     vec_default_construct (address () + oldlen, growby);
    1447    764211201 : }
    1448              : 
    1449              : /* Garbage collection support for vec<T, A, vl_embed>.  */
    1450              : 
    1451              : template<typename T>
    1452              : void
    1453   3854387169 : gt_ggc_mx (vec<T, va_gc> *v)
    1454              : {
    1455              :   static_assert (std::is_trivially_destructible <T>::value, "");
    1456              :   extern void gt_ggc_mx (T &);
    1457  78140807310 :   for (unsigned i = 0; i < v->length (); i++)
    1458  74286420141 :     gt_ggc_mx ((*v)[i]);
    1459   3854387169 : }
    1460              : 
    1461              : template<typename T>
    1462              : void
    1463              : gt_ggc_mx (vec<T, va_gc_atomic, vl_embed> *v ATTRIBUTE_UNUSED)
    1464              : {
    1465              :   static_assert (std::is_trivially_destructible <T>::value, "");
    1466              :   /* Nothing to do.  Vectors of atomic types wrt GC do not need to
    1467              :      be traversed.  */
    1468              : }
    1469              : 
    1470              : 
    1471              : /* PCH support for vec<T, A, vl_embed>.  */
    1472              : 
    1473              : template<typename T, typename A>
    1474              : void
    1475       876268 : gt_pch_nx (vec<T, A, vl_embed> *v)
    1476              : {
    1477              :   extern void gt_pch_nx (T &);
    1478      3059936 :   for (unsigned i = 0; i < v->length (); i++)
    1479      2183668 :     gt_pch_nx ((*v)[i]);
    1480       876268 : }
    1481              : 
    1482              : template<typename T>
    1483              : void
    1484              : gt_pch_nx (vec<T, va_gc_atomic, vl_embed> *)
    1485              : {
    1486              :   /* No pointers to note.  */
    1487              : }
    1488              : 
    1489              : template<typename T, typename A>
    1490              : void
    1491       496355 : gt_pch_nx (vec<T *, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
    1492              : {
    1493      1171284 :   for (unsigned i = 0; i < v->length (); i++)
    1494       674929 :     op (&((*v)[i]), NULL, cookie);
    1495       496355 : }
    1496              : 
    1497              : template<typename T, typename A>
    1498              : void
    1499       379913 : gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie)
    1500              : {
    1501              :   extern void gt_pch_nx (T *, gt_pointer_operator, void *);
    1502      1888652 :   for (unsigned i = 0; i < v->length (); i++)
    1503      1508739 :     gt_pch_nx (&((*v)[i]), op, cookie);
    1504       379913 : }
    1505              : 
    1506              : template<typename T>
    1507              : void
    1508              : gt_pch_nx (vec<T, va_gc_atomic, vl_embed> *, gt_pointer_operator, void *)
    1509              : {
    1510              :   /* No pointers to note.  */
    1511              : }
    1512              : 
    1513              : 
    1514              : /* Space efficient vector.  These vectors can grow dynamically and are
    1515              :    allocated together with their control data.  They are suited to be
    1516              :    included in data structures.  Prior to initial allocation, they
    1517              :    only take a single word of storage.
    1518              : 
    1519              :    These vectors are implemented as a pointer to an embeddable vector.
    1520              :    The semantics allow for this pointer to be NULL to represent empty
    1521              :    vectors.  This way, empty vectors occupy minimal space in the
    1522              :    structure containing them.
    1523              : 
    1524              :    Properties:
    1525              : 
    1526              :         - The whole vector and control data are allocated in a single
    1527              :           contiguous block.
    1528              :         - The whole vector may be re-allocated.
    1529              :         - Vector data may grow and shrink.
    1530              :         - Access and manipulation requires a pointer test and
    1531              :           indirection.
    1532              :         - It requires 1 word of storage (prior to vector allocation).
    1533              : 
    1534              : 
    1535              :    Limitations:
    1536              : 
    1537              :    These vectors must be PODs because they are stored in unions.
    1538              :    (http://en.wikipedia.org/wiki/Plain_old_data_structures).
    1539              :    As long as we use C++03, we cannot have constructors nor
    1540              :    destructors in classes that are stored in unions.  */
    1541              : 
    1542              : template<typename T, size_t N = 0>
    1543              : class auto_vec;
    1544              : 
    1545              : template<typename T>
    1546              : struct vec<T, va_heap, vl_ptr>
    1547              : {
    1548              : public:
    1549              :   /* Default ctors to ensure triviality.  Use value-initialization
    1550              :      (e.g., vec() or vec v{ };) or vNULL to create a zero-initialized
    1551              :      instance.  */
    1552              :   vec () = default;
    1553              :   vec (const vec &) = default;
    1554              :   /* Initialization from the generic vNULL.  */
    1555    920228944 :   vec (vnull): m_vec () { }
    1556              :   /* Same as default ctor: vec storage must be released manually.  */
    1557              :   ~vec () = default;
    1558              : 
    1559              :   /* Defaulted same as copy ctor.  */
    1560              :   vec& operator= (const vec &) = default;
    1561              : 
    1562              :   /* Prevent implicit conversion from auto_vec.  Use auto_vec::to_vec()
    1563              :      instead.  */
    1564              :   template <size_t N>
    1565              :   vec (auto_vec<T, N> &) = delete;
    1566              : 
    1567              :   template <size_t N>
    1568              :   void operator= (auto_vec<T, N> &) = delete;
    1569              : 
    1570              :   /* Memory allocation and deallocation for the embedded vector.
    1571              :      Needed because we cannot have proper ctors/dtors defined.  */
    1572              :   void create (unsigned nelems CXX_MEM_STAT_INFO);
    1573              :   void release (void);
    1574              : 
    1575              :   /* Vector operations.  */
    1576   2033706733 :   bool exists (void) const
    1577   1529931994 :   { return m_vec != NULL; }
    1578              : 
    1579  16958725717 :   bool is_empty (void) const
    1580  16121342562 :   { return m_vec ? m_vec->is_empty () : true; }
    1581              : 
    1582       834566 :   unsigned allocated (void) const
    1583       834566 :   { return m_vec ? m_vec->allocated () : 0; }
    1584              : 
    1585  88801339658 :   unsigned length (void) const
    1586  86021404673 :   { return m_vec ? m_vec->length () : 0; }
    1587              : 
    1588  11071920647 :   T *address (void)
    1589   5220050699 :   { return m_vec ? m_vec->address () : NULL; }
    1590              : 
    1591    257527105 :   const T *address (void) const
    1592    249782096 :   { return m_vec ? m_vec->address () : NULL; }
    1593              : 
    1594   8099832316 :   T *begin () { return address (); }
    1595     50206111 :   const T *begin () const { return address (); }
    1596   5165499897 :   T *end () { return begin () + length (); }
    1597     28086228 :   const T *end () const { return begin () + length (); }
    1598  10525045134 :   const T &operator[] (unsigned ix) const
    1599  10411731753 :   { return (*m_vec)[ix]; }
    1600      2209559 :   const T &last (void) const
    1601      2209559 :   { return m_vec->last (); }
    1602              : 
    1603      3136571 :   bool operator!=(const vec &other) const
    1604      3136571 :   { return !(*this == other); }
    1605              : 
    1606     83239594 :   bool operator==(const vec &other) const
    1607    166477438 :   { return address () == other.address (); }
    1608              : 
    1609  >11501*10^7 :   T &operator[] (unsigned ix)
    1610  91490470961 :   { return (*m_vec)[ix]; }
    1611              : 
    1612   9858370119 :   T &last (void)
    1613   9857600015 :   { return m_vec->last (); }
    1614              : 
    1615  60809721378 :   bool space (int nelems) const
    1616  60809721378 :   { return m_vec ? m_vec->space (nelems) : nelems == 0; }
    1617              : 
    1618              :   bool iterate (unsigned ix, T *p) const;
    1619              :   bool iterate (unsigned ix, T **p) const;
    1620              :   vec copy (ALONE_CXX_MEM_STAT_INFO) const;
    1621              :   bool reserve (unsigned, bool = false CXX_MEM_STAT_INFO);
    1622              :   bool reserve_exact (unsigned CXX_MEM_STAT_INFO);
    1623              :   void splice (const vec &);
    1624              :   void safe_splice (const vec & CXX_MEM_STAT_INFO);
    1625              :   T *quick_push (const T &);
    1626              :   T *safe_push (const T &CXX_MEM_STAT_INFO);
    1627              :   using pop_ret_type
    1628              :     = typename std::conditional <std::is_trivially_destructible <T>::value,
    1629              :                                  T &, void>::type;
    1630              :   pop_ret_type pop (void);
    1631              :   void truncate (unsigned);
    1632              :   void safe_grow (unsigned, bool = false CXX_MEM_STAT_INFO);
    1633              :   void safe_grow_cleared (unsigned, bool = false CXX_MEM_STAT_INFO);
    1634              :   void quick_grow (unsigned);
    1635              :   void quick_grow_cleared (unsigned);
    1636              :   void quick_insert (unsigned, const T &);
    1637              :   void safe_insert (unsigned, const T & CXX_MEM_STAT_INFO);
    1638              :   void ordered_remove (unsigned);
    1639              :   void unordered_remove (unsigned);
    1640              :   void block_remove (unsigned, unsigned);
    1641              :   void qsort (int (*) (const void *, const void *));
    1642              :   void sort (int (*) (const void *, const void *, void *), void *);
    1643              :   void stablesort (int (*) (const void *, const void *, void *), void *);
    1644              :   T *bsearch (const void *key, int (*compar)(const void *, const void *));
    1645              :   T *bsearch (const void *key,
    1646              :               int (*compar)(const void *, const void *, void *), void *);
    1647              :   unsigned lower_bound (T, bool (*)(const T &, const T &)) const;
    1648              :   bool contains (const T &search) const;
    1649              :   void reverse (void);
    1650              : 
    1651              :   bool using_auto_storage () const;
    1652              : 
    1653              :   /* FIXME - This field should be private, but we need to cater to
    1654              :              compilers that have stricter notions of PODness for types.  */
    1655              :   vec<T, va_heap, vl_embed> *m_vec;
    1656              : };
    1657              : 
    1658              : 
    1659              : /* auto_vec is a subclass of vec that automatically manages creating and
    1660              :    releasing the internal vector. If N is non zero then it has N elements of
    1661              :    internal storage.  The default is no internal storage, and you probably only
    1662              :    want to ask for internal storage for vectors on the stack because if the
    1663              :    size of the vector is larger than the internal storage that space is wasted.
    1664              :    */
    1665              : template<typename T, size_t N /* = 0 */>
    1666              : class auto_vec : public vec<T, va_heap>
    1667              : {
    1668              : public:
    1669  21506248526 :   auto_vec ()
    1670              :   {
    1671  21506248526 :     m_auto.embedded_init (N, 0, 1);
    1672              :     /* ???  Instead of initializing m_vec from &m_auto directly use an
    1673              :        expression that avoids referring to a specific member of 'this'
    1674              :        to derail the -Wstringop-overflow diagnostic code, avoiding
    1675              :        the impression that data accesses are supposed to be to the
    1676              :        m_auto member storage.  */
    1677  21506248526 :     size_t off = (char *) &m_auto - (char *) this;
    1678  20645835142 :     this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off);
    1679    245112477 :   }
    1680              : 
    1681    398362311 :   auto_vec (size_t s CXX_MEM_STAT_INFO)
    1682              :   {
    1683    398070041 :     if (s > N)
    1684              :       {
    1685     44929700 :         this->create (s PASS_MEM_STAT);
    1686     44929700 :         return;
    1687              :       }
    1688              : 
    1689    353432611 :     m_auto.embedded_init (N, 0, 1);
    1690              :     /* ???  See above.  */
    1691    353432611 :     size_t off = (char *) &m_auto - (char *) this;
    1692    353432611 :     this->m_vec = (vec<T, va_heap, vl_embed> *) ((char *) this + off);
    1693              :   }
    1694              : 
    1695  20908833136 :   ~auto_vec ()
    1696              :   {
    1697  19990192097 :     this->release ();
    1698   3877163469 :   }
    1699              : 
    1700              :   /* Explicitly convert to the base class.  There is no conversion
    1701              :      from a const auto_vec because a copy of the returned vec can
    1702              :      be used to modify *THIS.
    1703              :      This is a legacy function not to be used in new code.  */
    1704     18897251 :   vec<T, va_heap> to_vec_legacy () {
    1705     18897251 :     return *static_cast<vec<T, va_heap> *>(this);
    1706              :   }
    1707              : 
    1708              : private:
    1709              :   vec<T, va_heap, vl_embed> m_auto;
    1710              :   unsigned char m_data[sizeof (T) * N];
    1711              : };
    1712              : 
    1713              : /* auto_vec is a sub class of vec whose storage is released when it is
    1714              :   destroyed. */
    1715              : template<typename T>
    1716              : class auto_vec<T, 0> : public vec<T, va_heap>
    1717              : {
    1718              : public:
    1719   2354581950 :   auto_vec () { this->m_vec = NULL; }
    1720    203204540 :   auto_vec (size_t n CXX_MEM_STAT_INFO) { this->create (n PASS_MEM_STAT); }
    1721   2502314499 :   ~auto_vec () { this->release (); }
    1722              : 
    1723       698009 :   auto_vec (vec<T, va_heap>&& r)
    1724              :     {
    1725            0 :       gcc_assert (!r.using_auto_storage ());
    1726       698009 :       this->m_vec = r.m_vec;
    1727       698009 :       r.m_vec = NULL;
    1728       698009 :     }
    1729              : 
    1730      9052131 :   auto_vec (auto_vec<T> &&r)
    1731              :     {
    1732            0 :       gcc_assert (!r.using_auto_storage ());
    1733      9052131 :       this->m_vec = r.m_vec;
    1734      9052131 :       r.m_vec = NULL;
    1735      9052131 :     }
    1736              : 
    1737     39322553 :   auto_vec& operator= (vec<T, va_heap>&& r)
    1738              :     {
    1739     39322553 :       if (this == &r)
    1740              :         return *this;
    1741              : 
    1742            0 :       gcc_assert (!r.using_auto_storage ());
    1743     39322553 :       this->release ();
    1744     39322553 :       this->m_vec = r.m_vec;
    1745     39322553 :       r.m_vec = NULL;
    1746     39322553 :       return *this;
    1747              :     }
    1748              : 
    1749      8647658 :   auto_vec& operator= (auto_vec<T> &&r)
    1750              :     {
    1751      8647658 :       if (this == &r)
    1752              :         return *this;
    1753              : 
    1754            0 :       gcc_assert (!r.using_auto_storage ());
    1755      8647658 :       this->release ();
    1756      8647658 :       this->m_vec = r.m_vec;
    1757      8647658 :       r.m_vec = NULL;
    1758      8647658 :       return *this;
    1759              :     }
    1760              : 
    1761              :   /* Explicitly convert to the base class.  There is no conversion
    1762              :      from a const auto_vec because a copy of the returned vec can
    1763              :      be used to modify *THIS.
    1764              :      This is a legacy function not to be used in new code.  */
    1765          716 :   vec<T, va_heap> to_vec_legacy () {
    1766          716 :     return *static_cast<vec<T, va_heap> *>(this);
    1767              :   }
    1768              : 
    1769              :   // You probably don't want to copy a vector, so these are deleted to prevent
    1770              :   // unintentional use.  If you really need a copy of the vectors contents you
    1771              :   // can use copy ().
    1772              :   auto_vec (const auto_vec &) = delete;
    1773              :   auto_vec &operator= (const auto_vec &) = delete;
    1774              : };
    1775              : 
    1776              : 
    1777              : /* Allocate heap memory for pointer V and create the internal vector
    1778              :    with space for NELEMS elements.  If NELEMS is 0, the internal
    1779              :    vector is initialized to empty.  */
    1780              : 
    1781              : template<typename T>
    1782              : inline void
    1783      1923053 : vec_alloc (vec<T> *&v, unsigned nelems CXX_MEM_STAT_INFO)
    1784              : {
    1785      1923053 :   v = new vec<T>;
    1786      1923053 :   v->create (nelems PASS_MEM_STAT);
    1787      1923053 : }
    1788              : 
    1789              : 
    1790              : /* A subclass of auto_vec <char *> that frees all of its elements on
    1791              :    deletion.  */
    1792              : 
    1793         3435 : class auto_string_vec : public auto_vec <char *>
    1794              : {
    1795              :  public:
    1796              :   ~auto_string_vec ();
    1797              : };
    1798              : 
    1799              : /* A subclass of auto_vec <T *> that deletes all of its elements on
    1800              :    destruction.
    1801              : 
    1802              :    This is a crude way for a vec to "own" the objects it points to
    1803              :    and clean up automatically.
    1804              : 
    1805              :    For example, no attempt is made to delete elements when an item
    1806              :    within the vec is overwritten.
    1807              : 
    1808              :    We can't rely on gnu::unique_ptr within a container,
    1809              :    since we can't rely on move semantics in C++98.  */
    1810              : 
    1811              : template <typename T>
    1812              : class auto_delete_vec : public auto_vec <T *>
    1813              : {
    1814              :  public:
    1815       104727 :   auto_delete_vec () {}
    1816      7585289 :   auto_delete_vec (size_t s) : auto_vec <T *> (s) {}
    1817              : 
    1818              :   ~auto_delete_vec ();
    1819              : 
    1820              : private:
    1821              :   DISABLE_COPY_AND_ASSIGN(auto_delete_vec);
    1822              : };
    1823              : 
    1824              : /* Conditionally allocate heap memory for VEC and its internal vector.  */
    1825              : 
    1826              : template<typename T>
    1827              : inline void
    1828          158 : vec_check_alloc (vec<T, va_heap> *&vec, unsigned nelems CXX_MEM_STAT_INFO)
    1829              : {
    1830          158 :   if (!vec)
    1831           86 :     vec_alloc (vec, nelems PASS_MEM_STAT);
    1832              : }
    1833              : 
    1834              : 
    1835              : /* Free the heap memory allocated by vector V and set it to NULL.  */
    1836              : 
    1837              : template<typename T>
    1838              : inline void
    1839      6564455 : vec_free (vec<T> *&v)
    1840              : {
    1841      6564455 :   if (v == NULL)
    1842              :     return;
    1843              : 
    1844      1913675 :   v->release ();
    1845      1913675 :   delete v;
    1846      1913675 :   v = NULL;
    1847              : }
    1848              : 
    1849              : 
    1850              : /* Return iteration condition and update PTR to point to the IX'th
    1851              :    element of this vector.  Use this to iterate over the elements of a
    1852              :    vector as follows,
    1853              : 
    1854              :      for (ix = 0; v.iterate (ix, &ptr); ix++)
    1855              :        continue;  */
    1856              : 
    1857              : template<typename T>
    1858              : inline bool
    1859  57861108694 : vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const
    1860              : {
    1861  60565467523 :   if (m_vec)
    1862  66722155810 :     return m_vec->iterate (ix, ptr);
    1863              :   else
    1864              :     {
    1865    438358177 :       *ptr = 0;
    1866    438358177 :       return false;
    1867              :     }
    1868              : }
    1869              : 
    1870              : 
    1871              : /* Return iteration condition and update *PTR to point to the
    1872              :    IX'th element of this vector.  Use this to iterate over the
    1873              :    elements of a vector as follows,
    1874              : 
    1875              :      for (ix = 0; v->iterate (ix, &ptr); ix++)
    1876              :        continue;
    1877              : 
    1878              :    This variant is for vectors of objects.  */
    1879              : 
    1880              : template<typename T>
    1881              : inline bool
    1882   5583474310 : vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const
    1883              : {
    1884   5576199900 :   if (m_vec)
    1885   5997817805 :     return m_vec->iterate (ix, ptr);
    1886              :   else
    1887              :     {
    1888      1027054 :       *ptr = 0;
    1889      1027054 :       return false;
    1890              :     }
    1891              : }
    1892              : 
    1893              : 
    1894              : /* Convenience macro for forward iteration.  */
    1895              : #define FOR_EACH_VEC_ELT(V, I, P)                       \
    1896              :   for (I = 0; (V).iterate ((I), &(P)); ++(I))
    1897              : 
    1898              : #define FOR_EACH_VEC_SAFE_ELT(V, I, P)                  \
    1899              :   for (I = 0; vec_safe_iterate ((V), (I), &(P)); ++(I))
    1900              : 
    1901              : /* Likewise, but start from FROM rather than 0.  */
    1902              : #define FOR_EACH_VEC_ELT_FROM(V, I, P, FROM)            \
    1903              :   for (I = (FROM); (V).iterate ((I), &(P)); ++(I))
    1904              : 
    1905              : /* Convenience macro for reverse iteration.  */
    1906              : #define FOR_EACH_VEC_ELT_REVERSE(V, I, P)               \
    1907              :   for (I = (V).length () - 1;                           \
    1908              :        (V).iterate ((I), &(P));                             \
    1909              :        (I)--)
    1910              : 
    1911              : #define FOR_EACH_VEC_SAFE_ELT_REVERSE(V, I, P)          \
    1912              :   for (I = vec_safe_length (V) - 1;                     \
    1913              :        vec_safe_iterate ((V), (I), &(P));   \
    1914              :        (I)--)
    1915              : 
    1916              : /* auto_string_vec's dtor, freeing all contained strings, automatically
    1917              :    chaining up to ~auto_vec <char *>, which frees the internal buffer.  */
    1918              : 
    1919              : inline
    1920         3241 : auto_string_vec::~auto_string_vec ()
    1921              : {
    1922         3241 :   int i;
    1923         3241 :   char *str;
    1924      4018351 :   FOR_EACH_VEC_ELT (*this, i, str)
    1925      4015110 :     free (str);
    1926         3241 : }
    1927              : 
    1928              : /* auto_delete_vec's dtor, deleting all contained items, automatically
    1929              :    chaining up to ~auto_vec <T*>, which frees the internal buffer.  */
    1930              : 
    1931              : template <typename T>
    1932              : inline
    1933      8102517 : auto_delete_vec<T>::~auto_delete_vec ()
    1934              : {
    1935              :   int i;
    1936              :   T *item;
    1937     45100503 :   FOR_EACH_VEC_ELT (*this, i, item)
    1938     71986653 :     delete item;
    1939      8102517 : }
    1940              : 
    1941              : 
    1942              : /* Return a copy of this vector.  */
    1943              : 
    1944              : template<typename T>
    1945              : inline vec<T, va_heap, vl_ptr>
    1946    158674123 : vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const
    1947              : {
    1948    158674123 :   vec<T, va_heap, vl_ptr> new_vec{ };
    1949    143935827 :   if (length ())
    1950    143934440 :     new_vec.m_vec = m_vec->copy (ALONE_PASS_MEM_STAT);
    1951    158674123 :   return new_vec;
    1952              : }
    1953              : 
    1954              : 
    1955              : /* Ensure that the vector has at least RESERVE slots available (if
    1956              :    EXACT is false), or exactly RESERVE slots available (if EXACT is
    1957              :    true).
    1958              : 
    1959              :    This may create additional headroom if EXACT is false.
    1960              : 
    1961              :    Note that this can cause the embedded vector to be reallocated.
    1962              :    Returns true iff reallocation actually occurred.  */
    1963              : 
    1964              : template<typename T>
    1965              : inline bool
    1966  60644779684 : vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL)
    1967              : {
    1968  >12128*10^7 :   if (space (nelems))
    1969              :     return false;
    1970              : 
    1971              :   /* For now play a game with va_heap::reserve to hide our auto storage if any,
    1972              :      this is necessary because it doesn't have enough information to know the
    1973              :      embedded vector is in auto storage, and so should not be freed.  */
    1974   2265660924 :   vec<T, va_heap, vl_embed> *oldvec = m_vec;
    1975   2265660924 :   unsigned int oldsize = 0;
    1976   2265660924 :   bool handle_auto_vec = m_vec && using_auto_storage ();
    1977              :   if (handle_auto_vec)
    1978              :     {
    1979     24647590 :       m_vec = NULL;
    1980     24647590 :       oldsize = oldvec->length ();
    1981     24647590 :       nelems += oldsize;
    1982              :     }
    1983              : 
    1984   2265660924 :   va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT);
    1985   2265660924 :   if (handle_auto_vec)
    1986              :     {
    1987     24647590 :       vec_copy_construct (m_vec->address (), oldvec->address (), oldsize);
    1988     24647590 :       m_vec->m_vecpfx.m_num = oldsize;
    1989              :     }
    1990              : 
    1991              :   return true;
    1992              : }
    1993              : 
    1994              : 
    1995              : /* Ensure that this vector has exactly NELEMS slots available.  This
    1996              :    will not create additional headroom.  Note this can cause the
    1997              :    embedded vector to be reallocated.  Returns true iff reallocation
    1998              :    actually occurred.  */
    1999              : 
    2000              : template<typename T>
    2001              : inline bool
    2002   2011474531 : vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL)
    2003              : {
    2004   1888859880 :   return reserve (nelems, true PASS_MEM_STAT);
    2005              : }
    2006              : 
    2007              : 
    2008              : /* Create the internal vector and reserve NELEMS for it.  This is
    2009              :    exactly like vec::reserve, but the internal vector is
    2010              :    unconditionally allocated from scratch.  The old one, if it
    2011              :    existed, is lost.  */
    2012              : 
    2013              : template<typename T>
    2014              : inline void
    2015   1233151306 : vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL)
    2016              : {
    2017   1253437096 :   m_vec = NULL;
    2018    384671959 :   if (nelems > 0)
    2019    569646869 :     reserve_exact (nelems PASS_MEM_STAT);
    2020    384671959 : }
    2021              : 
    2022              : 
    2023              : /* Free the memory occupied by the embedded vector.  */
    2024              : 
    2025              : template<typename T>
    2026              : inline void
    2027  37603085465 : vec<T, va_heap, vl_ptr>::release (void)
    2028              : {
    2029  37603085465 :   if (!m_vec)
    2030              :     return;
    2031              : 
    2032  33585334713 :   if (using_auto_storage ())
    2033              :     {
    2034  31530308463 :       m_vec->truncate (0);
    2035  31530308463 :       return;
    2036              :     }
    2037              : 
    2038   2055026250 :   va_heap::release (m_vec);
    2039              : }
    2040              : 
    2041              : /* Copy the elements from SRC to the end of this vector as if by memcpy.
    2042              :    SRC and this vector must be allocated with the same memory
    2043              :    allocation mechanism. This vector is assumed to have sufficient
    2044              :    headroom available.  */
    2045              : 
    2046              : template<typename T>
    2047              : inline void
    2048     15258939 : vec<T, va_heap, vl_ptr>::splice (const vec<T, va_heap, vl_ptr> &src)
    2049              : {
    2050     14347784 :   if (src.length ())
    2051     13482803 :     m_vec->splice (*(src.m_vec));
    2052     15258939 : }
    2053              : 
    2054              : 
    2055              : /* Copy the elements in SRC to the end of this vector as if by memcpy.
    2056              :    SRC and this vector must be allocated with the same mechanism.
    2057              :    If there is not enough headroom in this vector, it will be reallocated
    2058              :    as needed.  */
    2059              : 
    2060              : template<typename T>
    2061              : inline void
    2062      1631561 : vec<T, va_heap, vl_ptr>::safe_splice (const vec<T, va_heap, vl_ptr> &src
    2063              :                                       MEM_STAT_DECL)
    2064              : {
    2065      1534308 :   if (src.length ())
    2066              :     {
    2067      1526965 :       reserve_exact (src.length ());
    2068      1526965 :       splice (src);
    2069              :     }
    2070      1631561 : }
    2071              : 
    2072              : 
    2073              : /* Push OBJ (a new element) onto the end of the vector.  There must be
    2074              :    sufficient space in the vector.  Return a pointer to the slot
    2075              :    where OBJ was inserted.  */
    2076              : 
    2077              : template<typename T>
    2078              : inline T *
    2079  66798137595 : vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
    2080              : {
    2081  43717253482 :   return m_vec->quick_push (obj);
    2082              : }
    2083              : 
    2084              : 
    2085              : /* Push a new element OBJ onto the end of this vector.  Reallocates
    2086              :    the embedded vector, if needed.  Return a pointer to the slot where
    2087              :    OBJ was inserted.  */
    2088              : 
    2089              : template<typename T>
    2090              : inline T *
    2091  57308164189 : vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL)
    2092              : {
    2093  57308164189 :   reserve (1, false PASS_MEM_STAT);
    2094  57308164200 :   return quick_push (obj);
    2095              : }
    2096              : 
    2097              : 
    2098              : /* Pop and return a reference to the last element off the end of the
    2099              :    vector.  If T has non-trivial destructor, this method just pops
    2100              :    last element and returns void.  */
    2101              : 
    2102              : template<typename T>
    2103              : inline typename vec<T, va_heap, vl_ptr>::pop_ret_type
    2104  36711500968 : vec<T, va_heap, vl_ptr>::pop (void)
    2105              : {
    2106  36624281782 :   return m_vec->pop ();
    2107              : }
    2108              : 
    2109              : 
    2110              : /* Set the length of the vector to LEN.  The new length must be less
    2111              :    than or equal to the current length.  This is an O(1) operation.  */
    2112              : 
    2113              : template<typename T>
    2114              : inline void
    2115  20359297300 : vec<T, va_heap, vl_ptr>::truncate (unsigned size)
    2116              : {
    2117  20359297300 :   if (m_vec)
    2118  20221597165 :     m_vec->truncate (size);
    2119              :   else
    2120    137700135 :     gcc_checking_assert (size == 0);
    2121  20359297300 : }
    2122              : 
    2123              : 
    2124              : /* Grow the vector to a specific length.  LEN must be as long or
    2125              :    longer than the current length.  The new elements are
    2126              :    uninitialized.  Reallocate the internal vector, if needed.  */
    2127              : 
    2128              : template<typename T>
    2129              : inline void
    2130    208892619 : vec<T, va_heap, vl_ptr>::safe_grow (unsigned len, bool exact MEM_STAT_DECL)
    2131              : {
    2132    251491780 :   unsigned oldlen = length ();
    2133     42599161 :   gcc_checking_assert (oldlen <= len);
    2134    208892619 :   reserve (len - oldlen, exact PASS_MEM_STAT);
    2135    208892619 :   if (m_vec)
    2136    208878506 :     m_vec->quick_grow (len);
    2137              :   else
    2138        14113 :     gcc_checking_assert (len == 0);
    2139    208892619 : }
    2140              : 
    2141              : 
    2142              : /* Grow the embedded vector to a specific length.  LEN must be as
    2143              :    long or longer than the current length.  The new elements are
    2144              :    initialized to zero.  Reallocate the internal vector, if needed.  */
    2145              : 
    2146              : template<typename T>
    2147              : inline void
    2148    600680274 : vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len, bool exact
    2149              :                                             MEM_STAT_DECL)
    2150              : {
    2151    735517261 :   unsigned oldlen = length ();
    2152    134836987 :   gcc_checking_assert (oldlen <= len);
    2153    600680274 :   reserve (len - oldlen, exact PASS_MEM_STAT);
    2154    600680274 :   if (m_vec)
    2155    600434271 :     m_vec->quick_grow_cleared (len);
    2156              :   else
    2157       246003 :     gcc_checking_assert (len == 0);
    2158    600680274 : }
    2159              : 
    2160              : 
    2161              : /* Same as vec::safe_grow but without reallocation of the internal vector.
    2162              :    If the vector cannot be extended, a runtime assertion will be triggered.  */
    2163              : 
    2164              : template<typename T>
    2165              : inline void
    2166     15906272 : vec<T, va_heap, vl_ptr>::quick_grow (unsigned len)
    2167              : {
    2168     15906272 :   gcc_checking_assert (m_vec);
    2169     15906272 :   m_vec->quick_grow (len);
    2170     15906272 : }
    2171              : 
    2172              : 
    2173              : /* Same as vec::quick_grow_cleared but without reallocation of the
    2174              :    internal vector. If the vector cannot be extended, a runtime
    2175              :    assertion will be triggered.  */
    2176              : 
    2177              : template<typename T>
    2178              : inline void
    2179     84209761 : vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len)
    2180              : {
    2181     84209761 :   gcc_checking_assert (m_vec);
    2182     84209761 :   m_vec->quick_grow_cleared (len);
    2183     84209761 : }
    2184              : 
    2185              : 
    2186              : /* Insert an element, OBJ, at the IXth position of this vector.  There
    2187              :    must be sufficient space.  */
    2188              : 
    2189              : template<typename T>
    2190              : inline void
    2191    245223868 : vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj)
    2192              : {
    2193    245223868 :   m_vec->quick_insert (ix, obj);
    2194          289 : }
    2195              : 
    2196              : 
    2197              : /* Insert an element, OBJ, at the IXth position of the vector.
    2198              :    Reallocate the embedded vector, if necessary.  */
    2199              : 
    2200              : template<typename T>
    2201              : inline void
    2202    245218162 : vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL)
    2203              : {
    2204    245218162 :   reserve (1, false PASS_MEM_STAT);
    2205    245218162 :   quick_insert (ix, obj);
    2206    245218162 : }
    2207              : 
    2208              : 
    2209              : /* Remove an element from the IXth position of this vector.  Ordering of
    2210              :    remaining elements is preserved.  This is an O(N) operation due to
    2211              :    a memmove.  */
    2212              : 
    2213              : template<typename T>
    2214              : inline void
    2215      1912550 : vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix)
    2216              : {
    2217      1912404 :   m_vec->ordered_remove (ix);
    2218       159107 : }
    2219              : 
    2220              : 
    2221              : /* Remove an element from the IXth position of this vector.  Ordering
    2222              :    of remaining elements is destroyed.  This is an O(1) operation.  */
    2223              : 
    2224              : template<typename T>
    2225              : inline void
    2226     40306857 : vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix)
    2227              : {
    2228     40306857 :   m_vec->unordered_remove (ix);
    2229      7307967 : }
    2230              : 
    2231              : 
    2232              : /* Remove LEN elements starting at the IXth.  Ordering is retained.
    2233              :    This is an O(N) operation due to memmove.  */
    2234              : 
    2235              : template<typename T>
    2236              : inline void
    2237        81360 : vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len)
    2238              : {
    2239        81360 :   m_vec->block_remove (ix, len);
    2240        55585 : }
    2241              : 
    2242              : 
    2243              : /* Sort the contents of this vector with qsort.  CMP is the comparison
    2244              :    function to pass to qsort.  */
    2245              : 
    2246              : template<typename T>
    2247              : inline void
    2248    967490647 : vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *))
    2249              : {
    2250    910414462 :   if (m_vec)
    2251     97330158 :     m_vec->qsort (cmp);
    2252     55158496 : }
    2253              : 
    2254              : /* Sort the contents of this vector with qsort.  CMP is the comparison
    2255              :    function to pass to qsort.  */
    2256              : 
    2257              : template<typename T>
    2258              : inline void
    2259      1617777 : vec<T, va_heap, vl_ptr>::sort (int (*cmp) (const void *, const void *,
    2260              :                                            void *), void *data)
    2261              : {
    2262        32156 :   if (m_vec)
    2263      1617288 :     m_vec->sort (cmp, data);
    2264              : }
    2265              : 
    2266              : /* Sort the contents of this vector with gcc_stablesort_r.  CMP is the
    2267              :    comparison function to pass to qsort.  */
    2268              : 
    2269              : template<typename T>
    2270              : inline void
    2271         7092 : vec<T, va_heap, vl_ptr>::stablesort (int (*cmp) (const void *, const void *,
    2272              :                                                  void *), void *data)
    2273              : {
    2274         6482 :   if (m_vec)
    2275         7092 :     m_vec->stablesort (cmp, data);
    2276              : }
    2277              : 
    2278              : /* Search the contents of the sorted vector with a binary search.
    2279              :    CMP is the comparison function to pass to bsearch.  */
    2280              : 
    2281              : template<typename T>
    2282              : inline T *
    2283        26674 : vec<T, va_heap, vl_ptr>::bsearch (const void *key,
    2284              :                                   int (*cmp) (const void *, const void *))
    2285              : {
    2286        26674 :   if (m_vec)
    2287        26674 :     return m_vec->bsearch (key, cmp);
    2288              :   return NULL;
    2289              : }
    2290              : 
    2291              : /* Search the contents of the sorted vector with a binary search.
    2292              :    CMP is the comparison function to pass to bsearch.  */
    2293              : 
    2294              : template<typename T>
    2295              : inline T *
    2296       199368 : vec<T, va_heap, vl_ptr>::bsearch (const void *key,
    2297              :                                   int (*cmp) (const void *, const void *,
    2298              :                                               void *), void *data)
    2299              : {
    2300       199368 :   if (m_vec)
    2301       199368 :     return m_vec->bsearch (key, cmp, data);
    2302              :   return NULL;
    2303              : }
    2304              : 
    2305              : 
    2306              : /* Find and return the first position in which OBJ could be inserted
    2307              :    without changing the ordering of this vector.  LESSTHAN is a
    2308              :    function that returns true if the first argument is strictly less
    2309              :    than the second.  */
    2310              : 
    2311              : template<typename T>
    2312              : inline unsigned
    2313    145974879 : vec<T, va_heap, vl_ptr>::lower_bound (T obj,
    2314              :                                       bool (*lessthan)(const T &, const T &))
    2315              :     const
    2316              : {
    2317    145974879 :   return m_vec ? m_vec->lower_bound (obj, lessthan) : 0;
    2318              : }
    2319              : 
    2320              : /* Return true if SEARCH is an element of V.  Note that this is O(N) in the
    2321              :    size of the vector and so should be used with care.  */
    2322              : 
    2323              : template<typename T>
    2324              : inline bool
    2325     52507564 : vec<T, va_heap, vl_ptr>::contains (const T &search) const
    2326              : {
    2327    105014342 :   return m_vec ? m_vec->contains (search) : false;
    2328              : }
    2329              : 
    2330              : /* Reverse content of the vector.  */
    2331              : 
    2332              : template<typename T>
    2333              : inline void
    2334      2225775 : vec<T, va_heap, vl_ptr>::reverse (void)
    2335              : {
    2336      2225775 :   unsigned l = length ();
    2337      2225775 :   T *ptr = address ();
    2338              : 
    2339      2594720 :   for (unsigned i = 0; i < l / 2; i++)
    2340       368945 :     std::swap (ptr[i], ptr[l - i - 1]);
    2341      2225775 : }
    2342              : 
    2343              : template<typename T>
    2344              : inline bool
    2345  34003525027 : vec<T, va_heap, vl_ptr>::using_auto_storage () const
    2346              : {
    2347  34003525027 :   return m_vec ? m_vec->m_vecpfx.m_using_auto_storage : false;
    2348              : }
    2349              : 
    2350              : /* Release VEC and call release of all element vectors.  */
    2351              : 
    2352              : template<typename T>
    2353              : inline void
    2354        11139 : release_vec_vec (vec<vec<T> > &vec)
    2355              : {
    2356        31495 :   for (unsigned i = 0; i < vec.length (); i++)
    2357        20356 :     vec[i].release ();
    2358              : 
    2359        11139 :   vec.release ();
    2360        11139 : }
    2361              : 
    2362              : // Provide a subset of the std::span functionality.  (We can't use std::span
    2363              : // itself because it's a C++20 feature.)
    2364              : //
    2365              : // In addition, provide an invalid value that is distinct from all valid
    2366              : // sequences (including the empty sequence).  This can be used to return
    2367              : // failure without having to use std::optional.
    2368              : //
    2369              : // There is no operator bool because it would be ambiguous whether it is
    2370              : // testing for a valid value or an empty sequence.
    2371              : template<typename T>
    2372              : class array_slice
    2373              : {
    2374              :   template<typename OtherT> friend class array_slice;
    2375              : 
    2376              : public:
    2377              :   using value_type = T;
    2378              :   using iterator = T *;
    2379              :   using const_iterator = const T *;
    2380              : 
    2381     38775533 :   array_slice () : m_base (nullptr), m_size (0) {}
    2382              : 
    2383              :   template<typename OtherT>
    2384     76575649 :   array_slice (array_slice<OtherT> other)
    2385              :     : m_base (other.m_base), m_size (other.m_size) {}
    2386              : 
    2387    995166133 :   array_slice (iterator base, unsigned int size)
    2388    120115420 :     : m_base (base), m_size (size) {}
    2389              : 
    2390              :   template<size_t N>
    2391     26736141 :   array_slice (T (&array)[N]) : m_base (array), m_size (N) {}
    2392              : 
    2393              :   template<typename OtherT>
    2394     30944283 :   array_slice (const vec<OtherT> &v)
    2395     32799906 :     : m_base (v.address ()), m_size (v.length ()) {}
    2396              : 
    2397              :   template<typename OtherT>
    2398     50887525 :   array_slice (vec<OtherT> &v)
    2399     50887525 :     : m_base (v.address ()), m_size (v.length ()) {}
    2400              : 
    2401              :   template<typename OtherT, typename A>
    2402         3455 :   array_slice (const vec<OtherT, A, vl_embed> *v)
    2403         3455 :     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
    2404              : 
    2405              :   template<typename OtherT, typename A>
    2406        72961 :   array_slice (vec<OtherT, A, vl_embed> *v)
    2407        72961 :     : m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
    2408              : 
    2409            0 :   iterator begin () {  gcc_checking_assert (is_valid ()); return m_base; }
    2410            0 :   iterator end () {  gcc_checking_assert (is_valid ()); return m_base + m_size; }
    2411              : 
    2412            0 :   const_iterator begin () const { gcc_checking_assert (is_valid ()); return m_base; }
    2413            0 :   const_iterator end () const { gcc_checking_assert (is_valid ()); return m_base + m_size; }
    2414              : 
    2415              :   value_type &front ();
    2416              :   value_type &back ();
    2417              :   value_type &operator[] (unsigned int i);
    2418              : 
    2419              :   const value_type &front () const;
    2420              :   const value_type &back () const;
    2421              :   const value_type &operator[] (unsigned int i) const;
    2422              : 
    2423    453569635 :   unsigned size () const { return m_size; }
    2424     44995435 :   size_t size_bytes () const { return m_size * sizeof (T); }
    2425    101706044 :   bool empty () const { return m_size == 0; }
    2426              : 
    2427              :   // An invalid array_slice that represents a failed operation.  This is
    2428              :   // distinct from an empty slice, which is a valid result in some contexts.
    2429      6216178 :   static array_slice invalid () { return { nullptr, ~0U }; }
    2430              : 
    2431              :   // True if the array is valid, false if it is an array like INVALID.
    2432   2784185656 :   bool is_valid () const { return m_base || m_size == 0; }
    2433              : 
    2434              : private:
    2435              :   iterator m_base;
    2436              :   unsigned int m_size;
    2437              : };
    2438              : 
    2439              : template<typename T>
    2440              : inline typename array_slice<T>::value_type &
    2441          289 : array_slice<T>::front ()
    2442              : {
    2443          289 :   gcc_checking_assert (m_size);
    2444          289 :   return m_base[0];
    2445              : }
    2446              : 
    2447              : template<typename T>
    2448              : inline const typename array_slice<T>::value_type &
    2449         4970 : array_slice<T>::front () const
    2450              : {
    2451         4970 :   gcc_checking_assert (m_size);
    2452         4970 :   return m_base[0];
    2453              : }
    2454              : 
    2455              : template<typename T>
    2456              : inline typename array_slice<T>::value_type &
    2457            0 : array_slice<T>::back ()
    2458              : {
    2459            0 :   gcc_checking_assert (m_size);
    2460            0 :   return m_base[m_size - 1];
    2461              : }
    2462              : 
    2463              : template<typename T>
    2464              : inline const typename array_slice<T>::value_type &
    2465    112268371 : array_slice<T>::back () const
    2466              : {
    2467    112268371 :   gcc_checking_assert (m_size);
    2468    112268371 :   return m_base[m_size - 1];
    2469              : }
    2470              : 
    2471              : template<typename T>
    2472              : inline typename array_slice<T>::value_type &
    2473    123189441 : array_slice<T>::operator[] (unsigned int i)
    2474              : {
    2475    123189441 :   gcc_checking_assert (i < m_size);
    2476    123189441 :   return m_base[i];
    2477              : }
    2478              : 
    2479              : template<typename T>
    2480              : inline const typename array_slice<T>::value_type &
    2481    141106850 : array_slice<T>::operator[] (unsigned int i) const
    2482              : {
    2483    141106850 :   gcc_checking_assert (i < m_size);
    2484    141106850 :   return m_base[i];
    2485              : }
    2486              : 
    2487              : template<typename T>
    2488              : array_slice<T>
    2489       150948 : make_array_slice (T *base, unsigned int size)
    2490              : {
    2491       150948 :   return array_slice<T> (base, size);
    2492              : }
    2493              : 
    2494              : #if (GCC_VERSION >= 3000)
    2495              : # pragma GCC poison m_vec m_vecpfx m_vecdata
    2496              : #endif
    2497              : 
    2498              : /* string_slice inherits from array_slice, specifically to refer to a substring
    2499              :    of a character array.
    2500              :    It includes some string like helpers.  */
    2501              : class string_slice : public array_slice<const char>
    2502              : {
    2503              : public:
    2504           20 :   string_slice () : array_slice<const char> () {}
    2505         2062 :   string_slice (const char *str) : array_slice (str, strlen (str)) {}
    2506          618 :   explicit string_slice (const char *str, size_t len)
    2507           36 :     : array_slice (str, len) {}
    2508          662 :   explicit string_slice (const char *start, const char *end)
    2509           76 :     : array_slice (start, end - start) {}
    2510              : 
    2511         1017 :   friend bool operator== (const string_slice &lhs, const string_slice &rhs)
    2512              :   {
    2513         1045 :     if (!lhs.is_valid () || !rhs.is_valid ())
    2514              :       return false;
    2515         1017 :     if (lhs.size () != rhs.size ())
    2516              :       return false;
    2517              :     /* Case where either is a NULL pointer and therefore, as both are valid,
    2518              :        both are empty slices with length 0.  */
    2519          495 :     if (lhs.size () == 0)
    2520              :       return true;
    2521          447 :     return memcmp (lhs.begin (), rhs.begin (), lhs.size ()) == 0;
    2522              :   }
    2523              : 
    2524           64 :   friend bool operator!= (const string_slice &lhs, const string_slice &rhs)
    2525              :   {
    2526           64 :     return !(lhs == rhs);
    2527              :   }
    2528              : 
    2529              :   /* Returns an invalid string_slice.  */
    2530          558 :   static string_slice invalid ()
    2531              :   {
    2532          558 :     return string_slice (nullptr, ~0U);
    2533              :   }
    2534              : 
    2535              :   /* tokenize is used to split a string by some deliminator into
    2536              :      string_slice's.  Similarly to the posix strtok_r.but without modifying the
    2537              :      input string, and returning all tokens which may be empty in the case
    2538              :      of an empty input string of consecutive deliminators.  */
    2539              :   static string_slice tokenize (string_slice *str, string_slice delims);
    2540              : 
    2541              :   /* Removes white space from the front and back of the string_slice.  */
    2542              :   string_slice strip ();
    2543              : 
    2544              :   /* Compares two string_slices in lexographical ordering.  */
    2545              :   static int strcmp (string_slice str1, string_slice str2);
    2546              : };
    2547              : 
    2548              : #endif // GCC_VEC_H
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.