OSDN Git Service

2006-12-12 Andrew Macleod <amacleod@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / vec.h
index 13c4ed6..1f13452 100644 (file)
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #ifndef GCC_VEC_H
 #define GCC_VEC_H
@@ -29,17 +29,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    out-of-line generic functions.  The vectors are designed to
    interoperate with the GTY machinery.
 
-   Because of the different behavior of objects and of pointers to
-   objects, there are two flavors.  One to deal with a vector of
-   pointers to objects, and one to deal with a vector of objects
-   themselves.  Both of these pass pointers to objects around -- in
-   the former case the pointers are stored into the vector and in the
-   latter case the pointers are dereferenced and the objects copied
-   into the vector.  Therefore, when using a vector of pointers, the
-   objects pointed to must be long lived, but when dealing with a
-   vector of objects, the source objects need not be.  The vector of
-   pointers API is also appropriate for small register sized objects
-   like integers.
+   Because of the different behavior of structure objects, scalar
+   objects and of pointers, there are three flavors, one for each of
+   these variants.  Both the structure object and pointer variants
+   pass pointers to objects around -- in the former case the pointers
+   are stored into the vector and in the latter case the pointers are
+   dereferenced and the objects copied into the vector.  The scalar
+   object variant is suitable for int-like objects, and the vector
+   elements are returned by value.
 
    There are both 'index' and 'iterate' accessors.  The iterator
    returns a boolean iteration condition and updates the iteration
@@ -96,20 +93,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    the 'space' predicate will tell you whether there is spare capacity
    in the vector.  You will not normally need to use these two functions.
    
-   Vector types are defined using a DEF_VEC_{O,P}(TYPEDEF) macro, to
+   Vector types are defined using a DEF_VEC_{O,P,I}(TYPEDEF) macro, to
    get the non-memory allocation version, and then a
-   DEF_VEC_ALLOC_{O,P}(TYPEDEF,ALLOC) macro to get memory managed
+   DEF_VEC_ALLOC_{O,P,I}(TYPEDEF,ALLOC) macro to get memory managed
    vectors.  Variables of vector type are declared using a
    VEC(TYPEDEF,ALLOC) macro.  The ALLOC argument specifies the
    allocation strategy, and can be either 'gc' or 'heap' for garbage
    collected and heap allocated respectively.  It can be 'none' to get
    a vector that must be explicitly allocated (for instance as a
-   trailing array of another structure).  The characters O and P
-   indicate whether TYPEDEF is a pointer (P) or object (O) type.  Be
-   careful to pick the correct one, as you'll get an awkward and
-   inefficient API if you get the wrong one.  There is a check, which
-   results in a compile-time warning, for the P versions, but there is
-   no check for the O versions, as that is not possible in plain C.
+   trailing array of another structure).  The characters O, P and I
+   indicate whether TYPEDEF is a pointer (P), object (O) or integral
+   (I) type.  Be careful to pick the correct one, as you'll get an
+   awkward and inefficient API if you use the wrong one.  There is a
+   check, which results in a compile-time warning, for the P and I
+   versions, but there is no check for the O versions, as that is not
+   possible in plain C.  Due to the way GTY works, you must annotate
+   any structures you wish to insert or reference from a vector with a
+   GTY(()) tag.  You need to do this even if you never declare the GC
+   allocated variants.
 
    An example of their use would be,
 
@@ -146,7 +147,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #define VEC_length(T,V)        (VEC_OP(T,base,length)(VEC_BASE(V)))
 
+
+/* Check if vector is empty
+   int VEC_T_empty(const VEC(T) *v);
+
+   Return nonzero if V is an empty vector (or V is NULL), zero otherwise.  */
+
+#define VEC_empty(T,V) (VEC_length (T,V) == 0)
+
+
 /* Get the final element of the vector.
+   T VEC_T_last(VEC(T) *v); // Integer
    T VEC_T_last(VEC(T) *v); // Pointer
    T *VEC_T_last(VEC(T) *v); // Object
 
@@ -155,6 +166,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define VEC_last(T,V)  (VEC_OP(T,base,last)(VEC_BASE(V) VEC_CHECK_INFO))
 
 /* Index into vector
+   T VEC_T_index(VEC(T) *v, unsigned ix); // Integer
    T VEC_T_index(VEC(T) *v, unsigned ix); // Pointer
    T *VEC_T_index(VEC(T) *v, unsigned ix); // Object
 
@@ -163,6 +175,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define VEC_index(T,V,I) (VEC_OP(T,base,index)(VEC_BASE(V),I VEC_CHECK_INFO))
 
 /* Iterate over vector
+   int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Integer
    int VEC_T_iterate(VEC(T) *v, unsigned ix, T &ptr); // Pointer
    int VEC_T_iterate(VEC(T) *v, unsigned ix, T *&ptr); // Object
 
@@ -201,6 +214,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define VEC_embedded_size(T,N)  (VEC_OP(T,base,embedded_size)(N))
 #define VEC_embedded_init(T,O,N) (VEC_OP(T,base,embedded_init)(VEC_BASE(O),N))
 
+/* Copy a vector.
+   VEC(T,A) *VEC_T_A_copy(VEC(T) *);
+
+   Copy the live elements of a vector into a new vector.  The new and
+   old vectors need not be allocated by the same mechanism.  */
+
+#define VEC_copy(T,A,V) (VEC_OP(T,A,copy)(VEC_BASE(V) MEM_STAT_INFO))
+
 /* Determine if a vector has additional capacity.
    
    int VEC_T_space (VEC(T) *v,int reserve)
@@ -228,6 +249,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
 
 /* Push object with no reallocation
+   T *VEC_T_quick_push (VEC(T) *v, T obj); // Integer
    T *VEC_T_quick_push (VEC(T) *v, T obj); // Pointer
    T *VEC_T_quick_push (VEC(T) *v, T *obj); // Object
    
@@ -240,6 +262,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,base,quick_push)(VEC_BASE(V),O VEC_CHECK_INFO))
 
 /* Push object with reallocation
+   T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Integer
    T *VEC_T_A_safe_push (VEC(T,A) *&v, T obj); // Pointer
    T *VEC_T_A_safe_push (VEC(T,A) *&v, T *obj); // Object
    
@@ -251,6 +274,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,A,safe_push)(&(V),O VEC_CHECK_INFO MEM_STAT_INFO))
 
 /* Pop element off end
+   T VEC_T_pop (VEC(T) *v);            // Integer
    T VEC_T_pop (VEC(T) *v);            // Pointer
    void VEC_T_pop (VEC(T) *v);         // Object
 
@@ -276,9 +300,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    uninitialized.  */
 
 #define VEC_safe_grow(T,A,V,I)         \
-       (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO))
+       (VEC_OP(T,A,safe_grow)(&(V),I VEC_CHECK_INFO MEM_STAT_INFO))
 
 /* Replace element
+   T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Integer
    T VEC_T_replace (VEC(T) *v, unsigned ix, T val); // Pointer
    T *VEC_T_replace (VEC(T) *v, unsigned ix, T *val);  // Object
    
@@ -292,6 +317,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,base,replace)(VEC_BASE(V),I,O VEC_CHECK_INFO))
 
 /* Insert object with no reallocation
+   T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Integer
    T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T val); // Pointer
    T *VEC_T_quick_insert (VEC(T) *v, unsigned ix, T *val); // Object
    
@@ -304,6 +330,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,base,quick_insert)(VEC_BASE(V),I,O VEC_CHECK_INFO))
 
 /* Insert object with reallocation
+   T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Integer
    T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T val); // Pointer
    T *VEC_T_A_safe_insert (VEC(T,A) *&v, unsigned ix, T *val); // Object
    
@@ -316,6 +343,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,A,safe_insert)(&(V),I,O VEC_CHECK_INFO MEM_STAT_INFO))
      
 /* Remove element retaining order
+   T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Integer
    T VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Pointer
    void VEC_T_ordered_remove (VEC(T) *v, unsigned ix); // Object
    
@@ -327,6 +355,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
        (VEC_OP(T,base,ordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
 
 /* Remove element destroying order
+   T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Integer
    T VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Pointer
    void VEC_T_unordered_remove (VEC(T) *v, unsigned ix); // Object
    
@@ -337,6 +366,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define VEC_unordered_remove(T,V,I)    \
        (VEC_OP(T,base,unordered_remove)(VEC_BASE(V),I VEC_CHECK_INFO))
 
+/* Remove a block of elements
+   void VEC_T_block_remove (VEC(T) *v, unsigned ix, unsigned len);
+   
+   Remove LEN elements starting at the IXth.  Ordering is retained.
+   This is an O(1) operation.  */
+
+#define VEC_block_remove(T,V,I,L)      \
+       (VEC_OP(T,base,block_remove)(VEC_BASE(V),I,L VEC_CHECK_INFO))
+
 /* Get the address of the array of elements
    T *VEC_T_address (VEC(T) v)
 
@@ -347,6 +385,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* Find the first index in the vector not less than the object.
    unsigned VEC_T_lower_bound (VEC(T) *v, const T val, 
+                               bool (*lessthan) (const T, const T)); // Integer
+   unsigned VEC_T_lower_bound (VEC(T) *v, const T val, 
                                bool (*lessthan) (const T, const T)); // Pointer
    unsigned VEC_T_lower_bound (VEC(T) *v, const T *val,
                                bool (*lessthan) (const T*, const T*)); // Object
@@ -397,6 +437,14 @@ extern void vec_assert_fail (const char *, const char * VEC_CHECK_DECL)
 
 /* Base of vector type, not user visible.  */     
 #define VEC_T(T,B)                                                       \
+typedef struct VEC(T,B)                                                  \
+{                                                                        \
+  unsigned num;                                                                  \
+  unsigned alloc;                                                        \
+  T vec[1];                                                              \
+} VEC(T,B)
+
+#define VEC_T_GTY(T,B)                                                   \
 typedef struct VEC(T,B) GTY(())                                                  \
 {                                                                        \
   unsigned num;                                                                  \
@@ -405,7 +453,7 @@ typedef struct VEC(T,B) GTY(())                                               \
 } VEC(T,B)
 
 /* Derived vector type, user visible.  */
-#define VEC_TA(T,B,A,GTY)                                                \
+#define VEC_TA_GTY(T,B,A,GTY)                                            \
 typedef struct VEC(T,A) GTY                                              \
 {                                                                        \
   VEC(T,B) base;                                                         \
@@ -414,20 +462,49 @@ typedef struct VEC(T,A) GTY                                                 \
 /* Convert to base type.  */
 #define VEC_BASE(P)  ((P) ? &(P)->base : 0)
 
+/* Vector of integer-like object.  */
+#if IN_GENGTYPE
+{"DEF_VEC_I", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
+{"DEF_VEC_ALLOC_I", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
+#else
+#define DEF_VEC_I(T)                                                     \
+static inline void VEC_OP (T,must_be,integral_type) (void)               \
+{                                                                        \
+  (void)~(T)0;                                                           \
+}                                                                        \
+                                                                         \
+VEC_T(T,base);                                                           \
+VEC_TA_GTY(T,base,none,);                                                \
+DEF_VEC_FUNC_P(T)                                                        \
+struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_I(T,A)                                             \
+VEC_TA_GTY(T,base,A,);                                                   \
+DEF_VEC_ALLOC_FUNC_I(T,A)                                                \
+struct vec_swallow_trailing_semi
+#endif
+
 /* Vector of pointer to object.  */
 #if IN_GENGTYPE
-{"DEF_VEC_P", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA (#0,#1,#2,#3)) ";", NULL},
+{"DEF_VEC_P", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
+{"DEF_VEC_ALLOC_P", VEC_STRINGIFY (VEC_TA_GTY (#0,#1,#2,#3)) ";", NULL},
 #else
-  
 #define DEF_VEC_P(T)                                                     \
-VEC_T(T,base);                                                           \
-                                                                         \
-static inline void VEC_OP (T,must,be_a_pointer_or_integer) (void)        \
+static inline void VEC_OP (T,must_be,pointer_type) (void)                \
 {                                                                        \
-  (void)((T)0 == (void *)0);                                             \
+  (void)((T)1 == (void *)1);                                             \
 }                                                                        \
                                                                          \
+VEC_T_GTY(T,base);                                                       \
+VEC_TA_GTY(T,base,none,);                                                \
+DEF_VEC_FUNC_P(T)                                                        \
+struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_P(T,A)                                             \
+VEC_TA_GTY(T,base,A,);                                                   \
+DEF_VEC_ALLOC_FUNC_P(T,A)                                                \
+struct vec_swallow_trailing_semi
+#endif
+
+#define DEF_VEC_FUNC_P(T)                                                \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)   \
 {                                                                        \
   return vec_ ? vec_->num : 0;                                           \
@@ -568,6 +645,17 @@ static inline T VEC_OP (T,base,unordered_remove)                     \
   return obj_;                                                           \
 }                                                                        \
                                                                          \
+static inline void VEC_OP (T,base,block_remove)                                  \
+     (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL)     \
+{                                                                        \
+  T *slot_;                                                              \
+                                                                         \
+  VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base);         \
+  slot_ = &vec_->vec[ix_];                                               \
+  vec_->num -= len_;                                                     \
+  memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T));         \
+}                                                                        \
+                                                                         \
 static inline T *VEC_OP (T,base,address)                                 \
      (VEC(T,base) *vec_)                                                 \
 {                                                                        \
@@ -598,13 +686,9 @@ static inline unsigned VEC_OP (T,base,lower_bound)                   \
           len_ = half_;                                                          \
      }                                                                   \
    return first_;                                                        \
-}                                                                        \
-                                                                         \
-VEC_TA(T,base,none,)
-  
-#define DEF_VEC_ALLOC_P(T,A)                                             \
-VEC_TA(T,base,A,);                                                       \
-                                                                         \
+}
+
+#define DEF_VEC_ALLOC_FUNC_P(T,A)                                        \
 static inline VEC(T,A) *VEC_OP (T,A,alloc)                               \
      (int alloc_ MEM_STAT_DECL)                                                  \
 {                                                                        \
@@ -620,6 +704,23 @@ static inline void VEC_OP (T,A,free)                                         \
   *vec_ = NULL;                                                                  \
 }                                                                        \
                                                                          \
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{                                                                        \
+  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  VEC (T,A) *new_vec_ = NULL;                                            \
+                                                                         \
+  if (len_)                                                              \
+    {                                                                    \
+      /* We must request exact size allocation, hence the negation. */   \
+      new_vec_ = (VEC (T,A) *)(vec_##A##_p_reserve                       \
+                              (NULL, -len_ PASS_MEM_STAT));              \
+                                                                         \
+      new_vec_->base.num = len_;                                         \
+      memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
+    }                                                                    \
+  return new_vec_;                                                       \
+}                                                                        \
+                                                                         \
 static inline int VEC_OP (T,A,reserve)                                   \
      (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)                  \
 {                                                                        \
@@ -659,20 +760,25 @@ static inline T *VEC_OP (T,A,safe_insert)                           \
                                                                          \
   return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_        \
                                       VEC_CHECK_PASS);                   \
-}                                                                        \
-                                                                         \
-struct vec_swallow_trailing_semi
-#endif
+}
 
 /* Vector of object.  */
 #if IN_GENGTYPE
-{"DEF_VEC_O", VEC_STRINGIFY (VEC_T(#0,#1)) ";", "none"},
-{"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA(#0,#1,#2,#3)) ";", NULL},
+{"DEF_VEC_O", VEC_STRINGIFY (VEC_T_GTY(#0,#1)) ";", "none"},
+{"DEF_VEC_ALLOC_O", VEC_STRINGIFY (VEC_TA_GTY(#0,#1,#2,#3)) ";", NULL},
 #else
-  
 #define DEF_VEC_O(T)                                                     \
-VEC_T(T,base);                                                           \
-                                                                         \
+VEC_T_GTY(T,base);                                                       \
+VEC_TA_GTY(T,base,none,);                                                \
+DEF_VEC_FUNC_O(T)                                                        \
+struct vec_swallow_trailing_semi
+#define DEF_VEC_ALLOC_O(T,A)                                             \
+VEC_TA_GTY(T,base,A,);                                                   \
+DEF_VEC_ALLOC_FUNC_O(T,A)                                                \
+struct vec_swallow_trailing_semi
+#endif
+
+#define DEF_VEC_FUNC_O(T)                                                \
 static inline unsigned VEC_OP (T,base,length) (const VEC(T,base) *vec_)          \
 {                                                                        \
   return vec_ ? vec_->num : 0;                                           \
@@ -800,6 +906,17 @@ static inline void VEC_OP (T,base,unordered_remove)                          \
   vec_->vec[ix_] = vec_->vec[--vec_->num];                               \
 }                                                                        \
                                                                          \
+static inline void VEC_OP (T,base,block_remove)                                  \
+     (VEC(T,base) *vec_, unsigned ix_, unsigned len_ VEC_CHECK_DECL)     \
+{                                                                        \
+  T *slot_;                                                              \
+                                                                         \
+  VEC_ASSERT (ix_ + len_ <= vec_->num, "block_remove", T, base);         \
+  slot_ = &vec_->vec[ix_];                                               \
+  vec_->num -= len_;                                                     \
+  memmove (slot_, slot_ + len_, (vec_->num - ix_) * sizeof (T));         \
+}                                                                        \
+                                                                         \
 static inline T *VEC_OP (T,base,address)                                 \
      (VEC(T,base) *vec_)                                                 \
 {                                                                        \
@@ -830,13 +947,9 @@ static inline unsigned VEC_OP (T,base,lower_bound)                   \
           len_ = half_;                                                          \
      }                                                                   \
    return first_;                                                        \
-}                                                                        \
-                                                                         \
-VEC_TA(T,base,none,)
+}
 
-#define DEF_VEC_ALLOC_O(T,A)                                             \
-VEC_TA(T,base,A,);                                                       \
-                                                                         \
+#define DEF_VEC_ALLOC_FUNC_O(T,A)                                        \
 static inline VEC(T,A) *VEC_OP (T,A,alloc)                               \
      (int alloc_ MEM_STAT_DECL)                                                  \
 {                                                                        \
@@ -847,6 +960,25 @@ static inline VEC(T,A) *VEC_OP (T,A,alloc)                           \
                                            PASS_MEM_STAT);               \
 }                                                                        \
                                                                          \
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{                                                                        \
+  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  VEC (T,A) *new_vec_ = NULL;                                            \
+                                                                         \
+  if (len_)                                                              \
+    {                                                                    \
+      /* We must request exact size allocation, hence the negation. */   \
+      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve                       \
+                              (NULL, -len_,                              \
+                               offsetof (VEC(T,A),base.vec), sizeof (T)  \
+                               PASS_MEM_STAT));                          \
+                                                                         \
+      new_vec_->base.num = len_;                                         \
+      memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
+    }                                                                    \
+  return new_vec_;                                                       \
+}                                                                        \
+                                                                         \
 static inline void VEC_OP (T,A,free)                                     \
      (VEC(T,A) **vec_)                                                   \
 {                                                                        \
@@ -880,7 +1012,6 @@ static inline void VEC_OP (T,A,safe_grow)                            \
   VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
                        VEC_CHECK_PASS PASS_MEM_STAT);                    \
   VEC_BASE (*vec_)->num = size_;                                         \
-  VEC_BASE (*vec_)->num = size_;                                         \
 }                                                                        \
                                                                          \
 static inline T *VEC_OP (T,A,safe_push)                                          \
@@ -899,9 +1030,89 @@ static inline T *VEC_OP (T,A,safe_insert)                           \
                                                                          \
   return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_        \
                                       VEC_CHECK_PASS);                   \
+}
+
+#define DEF_VEC_ALLOC_FUNC_I(T,A)                                        \
+static inline VEC(T,A) *VEC_OP (T,A,alloc)                               \
+     (int alloc_ MEM_STAT_DECL)                                                  \
+{                                                                        \
+  /* We must request exact size allocation, hence the negation.  */      \
+  return (VEC(T,A) *) vec_##A##_o_reserve (NULL, -alloc_,                \
+                                           offsetof (VEC(T,A),base.vec),  \
+                                          sizeof (T)                     \
+                                           PASS_MEM_STAT);               \
 }                                                                        \
                                                                          \
-struct vec_swallow_trailing_semi
-#endif
+static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
+{                                                                        \
+  size_t len_ = vec_ ? vec_->num : 0;                                    \
+  VEC (T,A) *new_vec_ = NULL;                                            \
+                                                                         \
+  if (len_)                                                              \
+    {                                                                    \
+      /* We must request exact size allocation, hence the negation. */   \
+      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve                       \
+                              (NULL, -len_,                              \
+                               offsetof (VEC(T,A),base.vec), sizeof (T)  \
+                               PASS_MEM_STAT));                          \
+                                                                         \
+      new_vec_->base.num = len_;                                         \
+      memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
+    }                                                                    \
+  return new_vec_;                                                       \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (T,A,free)                                     \
+     (VEC(T,A) **vec_)                                                   \
+{                                                                        \
+  if (*vec_)                                                             \
+    vec_##A##_free (*vec_);                                              \
+  *vec_ = NULL;                                                                  \
+}                                                                        \
+                                                                         \
+static inline int VEC_OP (T,A,reserve)                                   \
+     (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)                  \
+{                                                                        \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_),                          \
+                                      alloc_ < 0 ? -alloc_ : alloc_      \
+                                      VEC_CHECK_PASS);                   \
+                                                                         \
+  if (extend)                                                            \
+    *vec_ = (VEC(T,A) *) vec_##A##_o_reserve (*vec_, alloc_,             \
+                                             offsetof (VEC(T,A),base.vec),\
+                                             sizeof (T)                  \
+                                             PASS_MEM_STAT);             \
+                                                                         \
+  return extend;                                                         \
+}                                                                        \
+                                                                         \
+static inline void VEC_OP (T,A,safe_grow)                                \
+     (VEC(T,A) **vec_, int size_ VEC_CHECK_DECL MEM_STAT_DECL)           \
+{                                                                        \
+  VEC_ASSERT (size_ >= 0                                                 \
+             && VEC_OP(T,base,length) VEC_BASE(*vec_) <= (unsigned)size_, \
+                                                "grow", T, A);           \
+  VEC_OP (T,A,reserve) (vec_, (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) - size_ \
+                       VEC_CHECK_PASS PASS_MEM_STAT);                    \
+  VEC_BASE (*vec_)->num = size_;                                         \
+}                                                                        \
+                                                                         \
+static inline T *VEC_OP (T,A,safe_push)                                          \
+     (VEC(T,A) **vec_, const T obj_ VEC_CHECK_DECL MEM_STAT_DECL)        \
+{                                                                        \
+  VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);           \
+                                                                         \
+  return VEC_OP (T,base,quick_push) (VEC_BASE(*vec_), obj_ VEC_CHECK_PASS);  \
+}                                                                        \
+                                                                         \
+static inline T *VEC_OP (T,A,safe_insert)                                \
+     (VEC(T,A) **vec_, unsigned ix_, const T obj_                        \
+               VEC_CHECK_DECL MEM_STAT_DECL)                             \
+{                                                                        \
+  VEC_OP (T,A,reserve) (vec_, 1 VEC_CHECK_PASS PASS_MEM_STAT);           \
+                                                                         \
+  return VEC_OP (T,base,quick_insert) (VEC_BASE(*vec_), ix_, obj_        \
+                                      VEC_CHECK_PASS);                   \
+}
 
 #endif /* GCC_VEC_H */