This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH RFA: Tweak vec.[ch] to avoid undefined signed overflow


My ongoing work on producing a warning for cases where gcc relies on
undefined signed overflow produces warnings for vec.h.  They arise
because of the way that VEC_reserve uses a negative size to request an
exact reservation.  The code looks like this:

  int extend = !VEC_OP (T,base,space) (VEC_BASE(*vec_),			  \
				       alloc_ < 0 ? -alloc_ : alloc_	  \
				       VEC_CHECK_PASS);			  \

The conditional is optimized into abs (alloc_).  Within the called
function VEC_OP (T,base,space) we see this:

  VEC_ASSERT (alloc_ >= 0, "space", T, base);				  \

Here alloc_ is abs (alloc_) from the caller.  When VRP sees that the
result of abs in a test >= 0, it eliminates the test.

So that all seems fine.  But, we have to consider INT_MIN.  abs
(INT_MIN) is, of course, INT_MIN, which is a case of signed overflow.
The assumption made by VRP that abs (X) >= 0 is a case in which gcc
relies on the fact that signed overflow is undefined.

The effect here is that if some code ever manages to erroneously pass
INT_MIN to VEC_reserve, it will not get caught by the assert in VEC_OP
(t,base,space), because that assert will be removed.  It will
presumably be caught later when malloc fails.

There is no major issue here.  But after some discussion and some
thought, I think this code should stop overloading negative values,
and simply use a different function when it needs to reserve an exact
size.  I think this is slightly easier to understand and slightly more
efficient.

This patch passes bootstrap and testsuite run on i686-pc-linux-gnu.
OK for mainline?

Ian


gcc/ChangeLog:
2007-01-16  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.

gcc/cp/ChangeLog:
2007-01-16  Ian Lance Taylor  <iant@google.com>

	* class.c (add_method): Call VEC_reserve_exact rather than passing
	a negative size to VEC_reserve.


Index: gcc/vec.h
===================================================================
--- gcc/vec.h	(revision 120782)
+++ gcc/vec.h	(working copy)
@@ -66,8 +66,8 @@ Software Foundation, 51 Franklin Street,
    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,
 /* 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,
 #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,lo
 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
 									  \
   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
 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,lo
 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
 									  \
   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
 									  \
   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_;					  \
 }									  \
 									  \
Index: gcc/vec.c
===================================================================
--- gcc/vec.c	(revision 120782)
+++ gcc/vec.c	(working copy)
@@ -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_p
     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,33 +86,95 @@ calculate_allocation (const struct vec_p
   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.  */
+
+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, exact);
+  
+  if (!alloc)
+    return NULL;
+  
+  vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
+  ((struct vec_prefix *)vec)->alloc = alloc;
+  if (!pfx)
+    ((struct vec_prefix *)vec)->num = 0;
+  
+  return vec;
+}
+
+/* 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_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);
+  return vec_gc_o_reserve_1 (vec, reserve,
+			     offsetof (struct vec_prefix, vec),
+			     sizeof (void *), false
+			     PASS_MEM_STAT);
+}
+
+/* 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_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 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.  */
+/* 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)
+		  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 = alloc = calculate_allocation (pfx, reserve);
-  
+  unsigned alloc = calculate_allocation (pfx, reserve, exact);
+
   if (!alloc)
     return NULL;
   
-  vec = ggc_realloc_stat (vec, vec_offset + alloc * elt_size PASS_MEM_STAT);
+  vec = xrealloc (vec, vec_offset + alloc * elt_size);
   ((struct vec_prefix *)vec)->alloc = alloc;
   if (!pfx)
     ((struct vec_prefix *)vec)->num = 0;
@@ -124,9 +187,21 @@ vec_gc_o_reserve (void *vec, int reserve
 void *
 vec_heap_p_reserve (void *vec, int reserve MEM_STAT_DECL)
 {
-  return vec_heap_o_reserve (vec, reserve,
-			     offsetof (struct vec_prefix, vec), sizeof (void *)
-			     PASS_MEM_STAT);
+  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.  */
@@ -135,18 +210,18 @@ void *
 vec_heap_o_reserve (void *vec, int reserve, size_t vec_offset, size_t elt_size
 		    MEM_STAT_DECL)
 {
-  struct vec_prefix *pfx = vec;
-  unsigned alloc = calculate_allocation (pfx, reserve);
+  return vec_heap_o_reserve_1 (vec, reserve, vec_offset, elt_size, false
+			       PASS_MEM_STAT);
+}
 
-  if (!alloc)
-    return NULL;
-  
-  vec = xrealloc (vec, vec_offset + alloc * elt_size);
-  ((struct vec_prefix *)vec)->alloc = alloc;
-  if (!pfx)
-    ((struct vec_prefix *)vec)->num = 0;
-  
-  return vec;
+/* 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
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c	(revision 120782)
+++ gcc/cp/class.c	(working copy)
@@ -1071,9 +1071,15 @@ add_method (tree type, tree method, tree
 
   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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]