OSDN Git Service

./:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jan 2007 17:42:10 +0000 (17:42 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jan 2007 17:42:10 +0000 (17:42 +0000)
* vec.h (VEC_reserve_exact): Define.
(vec_gc_p_reserve_exact): Declare.
(vec_gc_o_reserve_exact): Declare.
(vec_heap_p_reserve_exact): Declare.
(vec_heap_o_reserve_exact): Declare.
(VEC_OP (T,A,reserve_exact)): New static inline function, three
versions.
(VEC_OP (T,A,reserve)) [all versions]: Remove handling of
negative parameter.
(VEC_OP (T,A,alloc)) [all versions]: Call ...reserve_exact.
(VEC_OP (T,A,copy)) [all versions]: Likewise.
(VEC_OP (T,a,safe_grow)) [all versions]: Likewise.
* vec.c (calculate_allocation): Add exact parameter.  Change all
callers.
(vec_gc_o_reserve_1): New static function, from vec_gc_o_reserve.
(vec_gc_p_reserve, vec_gc_o_reserve): Call vec_gc_o_reserve_1.
(vec_gc_p_reserve_exact, vec_gc_o_reserve_exact): New functions.
(vec_heap_o_reserve_1): New static function, from vec_heap_o_reserve.
(vec_heap_p_reserve, vec_heap_o_reserve): Call vec_heap_o_reserve_1.
(vec_heap_p_reserve_exact): New function.
(vec_heap_o_reserve_exact): New function.
cp/:
* class.c (add_method): Call VEC_reserve_exact rather than passing
a negative size to VEC_reserve.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120861 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/vec.c
gcc/vec.h

index 4045c4b..1b8bbce 100644 (file)
@@ -1,3 +1,27 @@
+2007-01-17  Ian Lance Taylor  <iant@google.com>
+
+       * vec.h (VEC_reserve_exact): Define.
+       (vec_gc_p_reserve_exact): Declare.
+       (vec_gc_o_reserve_exact): Declare.
+       (vec_heap_p_reserve_exact): Declare.
+       (vec_heap_o_reserve_exact): Declare.
+       (VEC_OP (T,A,reserve_exact)): New static inline function, three
+       versions.
+       (VEC_OP (T,A,reserve)) [all versions]: Remove handling of
+       negative parameter.
+       (VEC_OP (T,A,alloc)) [all versions]: Call ...reserve_exact.
+       (VEC_OP (T,A,copy)) [all versions]: Likewise.
+       (VEC_OP (T,a,safe_grow)) [all versions]: Likewise.
+       * vec.c (calculate_allocation): Add exact parameter.  Change all
+       callers.
+       (vec_gc_o_reserve_1): New static function, from vec_gc_o_reserve.
+       (vec_gc_p_reserve, vec_gc_o_reserve): Call vec_gc_o_reserve_1.
+       (vec_gc_p_reserve_exact, vec_gc_o_reserve_exact): New functions.
+       (vec_heap_o_reserve_1): New static function, from vec_heap_o_reserve.
+       (vec_heap_p_reserve, vec_heap_o_reserve): Call vec_heap_o_reserve_1.
+       (vec_heap_p_reserve_exact): New function.
+       (vec_heap_o_reserve_exact): New function.
+
 2007-01-17  Jan Hubicka  <jh@suse.cz>
 
        * ipa-type-escape.c (look_for_casts): Revamp using handled_component_p.
index 12a3cc6..5123c18 100644 (file)
@@ -1,3 +1,8 @@
+2007-01-17  Ian Lance Taylor  <iant@google.com>
+
+       * class.c (add_method): Call VEC_reserve_exact rather than passing
+       a negative size to VEC_reserve.
+
 2007-01-11  Simon Martin  <simartin@users.sourceforge.net>
 
        PR c++/29573
index b56ef84..3e0758a 100644 (file)
@@ -1071,9 +1071,15 @@ add_method (tree type, tree method, tree using_decl)
 
   if (insert_p)
     {
+      bool reallocated;
+
       /* We only expect to add few methods in the COMPLETE_P case, so
         just make room for one more method in that case.  */
-      if (VEC_reserve (tree, gc, method_vec, complete_p ? -1 : 1))
+      if (complete_p)
+       reallocated = VEC_reserve_exact (tree, gc, method_vec, 1);
+      else
+       reallocated = VEC_reserve (tree, gc, method_vec, 1);
+      if (reallocated)
        CLASSTYPE_METHOD_VEC (type) = method_vec;
       if (slot == VEC_length (tree, method_vec))
        VEC_quick_push (tree, method_vec, overload);
index cc62b91..9e9dd85 100644 (file)
--- a/gcc/vec.c
+++ b/gcc/vec.c
@@ -40,16 +40,17 @@ struct vec_prefix
   void *vec[1];
 };
 
-/* Calculate the new ALLOC value, making sure that abs(RESERVE) slots
-   are free.  If RESERVE < 0 grow exactly, otherwise grow
-   exponentially.  */
+/* Calculate the new ALLOC value, making sure that RESERVE slots are
+   free.  If EXACT grow exactly, otherwise grow exponentially.  */
 
 static inline unsigned
-calculate_allocation (const struct vec_prefix *pfx, int reserve)
+calculate_allocation (const struct vec_prefix *pfx, int reserve, bool exact)
 {
   unsigned alloc = 0;
   unsigned num = 0;
 
+  gcc_assert (reserve >= 0);
+
   if (pfx)
     {
       alloc = pfx->alloc;
@@ -61,11 +62,11 @@ calculate_allocation (const struct vec_prefix *pfx, int reserve)
     return 0;
   
   /* We must have run out of room.  */
-  gcc_assert (alloc - num < (unsigned)(reserve < 0 ? -reserve : reserve));
+  gcc_assert (alloc - num < (unsigned) reserve);
   
-  if (reserve < 0)
+  if (exact)
     /* Exact size.  */
-    alloc = num + -reserve;
+    alloc = num + reserve;
   else
     {
       /* Exponential growth. */
@@ -85,28 +86,18 @@ calculate_allocation (const struct vec_prefix *pfx, int reserve)
   return alloc;
 }
 
-/* Ensure there are at least abs(RESERVE) free slots in VEC.  If
-   RESERVE < 0 grow exactly, else grow exponentially.  As a special
-   case, if VEC is NULL, and RESERVE is 0, no vector will be created. */
+/* Ensure there are at least RESERVE free slots in VEC.  If EXACT grow
+   exactly, else grow exponentially.  As a special case, if VEC is
+   NULL and RESERVE is 0, no vector will be created.  The vector's
+   trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
+   sized elements.  */
 
-void *
-vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
-{
-  return vec_gc_o_reserve (vec, reserve,
-                          offsetof (struct vec_prefix, vec), sizeof (void *)
-                          PASS_MEM_STAT);
-}
-
-/* As vec_gc_p_reserve, but for object vectors.  The vector's trailing
-   array is at VEC_OFFSET offset and consists of ELT_SIZE sized
-   elements.  */
-
-void *
-vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
-                  MEM_STAT_DECL)
+static void *
+vec_gc_o_reserve_1 (void *vec, int reserve, size_t vec_offset, size_t elt_size,
+                   bool exact MEM_STAT_DECL)
 {
   struct vec_prefix *pfx = vec;
-  unsigned alloc = alloc = calculate_allocation (pfx, reserve);
+  unsigned alloc = alloc = calculate_allocation (pfx, reserve, exact);
   
   if (!alloc)
     return NULL;
@@ -119,24 +110,66 @@ vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
   return vec;
 }
 
-/* As for vec_gc_p_reserve, but for heap allocated vectors.  */
+/* Ensure there are at least RESERVE free slots in VEC, growing
+   exponentially.  If RESERVE < 0 grow exactly, else grow
+   exponentially.  As a special case, if VEC is NULL, and RESERVE is
+   0, no vector will be created. */
 
 void *
-vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
+vec_gc_p_reserve (void *vec, int reserve MEM_STAT_DECL)
 {
-  return vec_heap_o_reserve (vec, reserve,
-                            offsetof (struct vec_prefix, vec), sizeof (void *)
+  return vec_gc_o_reserve_1 (vec, reserve,
+                            offsetof (struct vec_prefix, vec),
+                            sizeof (void *), false
                             PASS_MEM_STAT);
 }
 
-/* As for vec_gc_o_reserve, but for heap allocated vectors.  */
+/* Ensure there are at least RESERVE free slots in VEC, growing
+   exactly.  If RESERVE < 0 grow exactly, else grow exponentially.  As
+   a special case, if VEC is NULL, and RESERVE is 0, no vector will be
+   created. */
 
 void *
-vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
-                   MEM_STAT_DECL)
+vec_gc_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
+{
+  return vec_gc_o_reserve_1 (vec, reserve,
+                            offsetof (struct vec_prefix, vec),
+                            sizeof (void *), true
+                            PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve, but for object vectors.  The vector's
+   trailing array is at VEC_OFFSET offset and consists of ELT_SIZE
+   sized elements.  */
+
+void *
+vec_gc_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
+                 MEM_STAT_DECL)
+{
+  return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
+                            PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve_exact, but for object vectors.  The
+   vector's trailing array is at VEC_OFFSET offset and consists of
+   ELT_SIZE sized elements.  */
+
+void *
+vec_gc_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
+                       size_t elt_size MEM_STAT_DECL)
+{
+  return vec_gc_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
+                            PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve_1, but for heap allocated vectors.  */
+
+static void *
+vec_heap_o_reserve_1 (void *vec, int reserve, size_t vec_offset,
+                     size_t elt_size, bool exact MEM_STAT_DECL)
 {
   struct vec_prefix *pfx = vec;
-  unsigned alloc = calculate_allocation (pfx, reserve);
+  unsigned alloc = calculate_allocation (pfx, reserve, exact);
 
   if (!alloc)
     return NULL;
@@ -149,6 +182,48 @@ vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
   return vec;
 }
 
+/* As for vec_gc_p_reserve, but for heap allocated vectors.  */
+
+void *
+vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
+{
+  return vec_heap_o_reserve_1 (vec, reserve,
+                              offsetof (struct vec_prefix, vec),
+                              sizeof (void *), false
+                              PASS_MEM_STAT);
+}
+
+/* As for vec_gc_p_reserve_exact, but for heap allocated vectors.  */
+
+void *
+vec_heap_p_reserve_exact (void *vec, int reserve MEM_STAT_DECL)
+{
+  return vec_heap_o_reserve_1 (vec, reserve,
+                              offsetof (struct vec_prefix, vec),
+                              sizeof (void *), true
+                              PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve, but for heap allocated vectors.  */
+
+void *
+vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
+                   MEM_STAT_DECL)
+{
+  return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
+                              PASS_MEM_STAT);
+}
+
+/* As for vec_gc_o_reserve_exact, but for heap allocated vectors.  */
+
+void *
+vec_heap_o_reserve_exact (void *vec, int reserve, size_t vec_offset,
+                         size_t elt_size MEM_STAT_DECL)
+{
+  return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, true
+                              PASS_MEM_STAT);
+}
+
 #if ENABLE_CHECKING
 /* Issue a vector domain error, and then fall over.  */
 
index 44ec8a4..3bc6566 100644 (file)
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -66,8 +66,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
    least as many elements as you ask for, it will exponentially
    increase if there are too few spare slots.  If you want reserve a
    specific number of slots, but do not want the exponential increase
-   (for instance, you know this is the last allocation), use a
-   negative number for reservation.  You can also create a vector of a
+   (for instance, you know this is the last allocation), use the
+   reserve_exact operation.  You can also create a vector of a
    specific size from the get go.
 
    You should prefer the push and pop operations, as they append and
@@ -238,16 +238,25 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 /* Reserve space.
    int VEC_T_A_reserve(VEC(T,A) *&v, int reserve);
 
-   Ensure that V has at least abs(RESERVE) slots available.  The
-   signedness of RESERVE determines the reallocation behavior.  A
-   negative value will not create additional headroom beyond that
-   requested.  A positive value will create additional headroom.  Note
-   this can cause V to be reallocated.  Returns nonzero iff
-   reallocation actually occurred.  */
+   Ensure that V has at least RESERVE slots available.  This will
+   create additional headroom.  Note this can cause V to be
+   reallocated.  Returns nonzero iff reallocation actually
+   occurred.  */
 
 #define VEC_reserve(T,A,V,R)   \
        (VEC_OP(T,A,reserve)(&(V),R VEC_CHECK_INFO MEM_STAT_INFO))
 
+/* Reserve space exactly.
+   int VEC_T_A_reserve_exact(VEC(T,A) *&v, int reserve);
+
+   Ensure that V has at least RESERVE slots available.  This will not
+   create additional headroom.  Note this can cause V to be
+   reallocated.  Returns nonzero iff reallocation actually
+   occurred.  */
+
+#define VEC_reserve_exact(T,A,V,R)     \
+       (VEC_OP(T,A,reserve_exact)(&(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
@@ -411,11 +420,17 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #if !IN_GENGTYPE
 /* Reallocate an array of elements with prefix.  */
 extern void *vec_gc_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_gc_p_reserve_exact (void *, int MEM_STAT_DECL);
 extern void *vec_gc_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_gc_o_reserve_exact (void *, int, size_t, size_t
+                                    MEM_STAT_DECL);
 extern void ggc_free (void *);
 #define vec_gc_free(V) ggc_free (V)
 extern void *vec_heap_p_reserve (void *, int MEM_STAT_DECL);
+extern void *vec_heap_p_reserve_exact (void *, int MEM_STAT_DECL);
 extern void *vec_heap_o_reserve (void *, int, size_t, size_t MEM_STAT_DECL);
+extern void *vec_heap_o_reserve_exact (void *, int, size_t, size_t
+                                      MEM_STAT_DECL);
 #define vec_heap_free(V) free (V)
 
 #if ENABLE_CHECKING
@@ -702,8 +717,8 @@ static inline unsigned VEC_OP (T,base,lower_bound)                    \
 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##_p_reserve (NULL, -alloc_ PASS_MEM_STAT);  \
+  return (VEC(T,A) *) vec_##A##_p_reserve_exact (NULL, alloc_            \
+                                                PASS_MEM_STAT);          \
 }                                                                        \
                                                                          \
 static inline void VEC_OP (T,A,free)                                     \
@@ -721,9 +736,8 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
                                                                          \
   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_ = (VEC (T,A) *)(vec_##A##_p_reserve_exact                 \
+                              (NULL, len_ PASS_MEM_STAT));               \
                                                                          \
       new_vec_->base.num = len_;                                         \
       memcpy (new_vec_->base.vec, vec_->vec, sizeof (T) * len_);         \
@@ -734,8 +748,7 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
 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_      \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
                                       VEC_CHECK_PASS);                   \
                                                                          \
   if (extend)                                                            \
@@ -744,14 +757,28 @@ static inline int VEC_OP (T,A,reserve)                                      \
   return extend;                                                         \
 }                                                                        \
                                                                          \
+static inline int VEC_OP (T,A,reserve_exact)                             \
+     (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)                  \
+{                                                                        \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
+                                      VEC_CHECK_PASS);                   \
+                                                                         \
+  if (extend)                                                            \
+    *vec_ = (VEC(T,A) *) vec_##A##_p_reserve_exact (*vec_, alloc_        \
+                                                   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_OP (T,A,reserve_exact) (vec_,                                      \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             VEC_CHECK_PASS PASS_MEM_STAT);              \
   VEC_BASE (*vec_)->num = size_;                                         \
 }                                                                        \
                                                                          \
@@ -972,11 +999,10 @@ static inline unsigned VEC_OP (T,base,lower_bound)                          \
 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);               \
+  return (VEC(T,A) *) vec_##A##_o_reserve_exact (NULL, alloc_,           \
+                                                offsetof (VEC(T,A),base.vec), \
+                                                sizeof (T)               \
+                                                PASS_MEM_STAT);          \
 }                                                                        \
                                                                          \
 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
@@ -986,9 +1012,8 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
                                                                          \
   if (len_)                                                              \
     {                                                                    \
-      /* We must request exact size allocation, hence the negation. */   \
-      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve                       \
-                              (NULL, -len_,                              \
+      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact                 \
+                              (NULL, len_,                               \
                                offsetof (VEC(T,A),base.vec), sizeof (T)  \
                                PASS_MEM_STAT));                          \
                                                                          \
@@ -1009,8 +1034,7 @@ static inline void VEC_OP (T,A,free)                                        \
 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_      \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
                                       VEC_CHECK_PASS);                   \
                                                                          \
   if (extend)                                                            \
@@ -1022,14 +1046,30 @@ static inline int VEC_OP (T,A,reserve)                                    \
   return extend;                                                         \
 }                                                                        \
                                                                          \
+static inline int VEC_OP (T,A,reserve_exact)                                     \
+     (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)                  \
+{                                                                        \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
+                                      VEC_CHECK_PASS);                   \
+                                                                         \
+  if (extend)                                                            \
+    *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact                       \
+                        (*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_OP (T,A,reserve_exact) (vec_,                                      \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             VEC_CHECK_PASS PASS_MEM_STAT);              \
   VEC_BASE (*vec_)->num = size_;                                         \
 }                                                                        \
                                                                          \
@@ -1064,11 +1104,9 @@ static inline T *VEC_OP (T,A,safe_insert)                                  \
 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);               \
+  return (VEC(T,A) *) vec_##A##_o_reserve_exact                                  \
+                     (NULL, alloc_, offsetof (VEC(T,A),base.vec),        \
+                      sizeof (T) PASS_MEM_STAT);                         \
 }                                                                        \
                                                                          \
 static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
@@ -1078,9 +1116,8 @@ static inline VEC(T,A) *VEC_OP (T,A,copy) (VEC(T,base) *vec_ MEM_STAT_DECL) \
                                                                          \
   if (len_)                                                              \
     {                                                                    \
-      /* We must request exact size allocation, hence the negation. */   \
-      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve                       \
-                              (NULL, -len_,                              \
+      new_vec_ = (VEC (T,A) *)(vec_##A##_o_reserve_exact                 \
+                              (NULL, len_,                               \
                                offsetof (VEC(T,A),base.vec), sizeof (T)  \
                                PASS_MEM_STAT));                          \
                                                                          \
@@ -1101,8 +1138,7 @@ static inline void VEC_OP (T,A,free)                                        \
 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_      \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
                                       VEC_CHECK_PASS);                   \
                                                                          \
   if (extend)                                                            \
@@ -1114,14 +1150,29 @@ static inline int VEC_OP (T,A,reserve)                                    \
   return extend;                                                         \
 }                                                                        \
                                                                          \
+static inline int VEC_OP (T,A,reserve_exact)                                     \
+     (VEC(T,A) **vec_, int alloc_ VEC_CHECK_DECL MEM_STAT_DECL)                  \
+{                                                                        \
+  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_), alloc_           \
+                                      VEC_CHECK_PASS);                   \
+                                                                         \
+  if (extend)                                                            \
+    *vec_ = (VEC(T,A) *) vec_##A##_o_reserve_exact                       \
+                        (*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_OP (T,A,reserve_exact) (vec_,                                      \
+                             size_ - (int)(*vec_ ? VEC_BASE(*vec_)->num : 0) \
+                             VEC_CHECK_PASS PASS_MEM_STAT);              \
   VEC_BASE (*vec_)->num = size_;                                         \
 }                                                                        \
                                                                          \