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]

C++ PATCH: PR 10300


Here is the PR c++/10300 patch for the mainline.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark at codesourcery dot com

2003-04-12  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/10300
	* init.c (build_new_1): Reorganize.

2003-04-13  Mark Mitchell  <mark at codesourcery dot com>

	PR c++/10300
	* g++.dg/init/new5.C: New test.

Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.315
diff -c -5 -p -r1.315 init.c
*** cp/init.c	16 Mar 2003 14:36:42 -0000	1.315
--- cp/init.c	13 Apr 2003 17:50:44 -0000
*************** get_cookie_size (type)
*** 2152,2168 ****
  static tree
  build_new_1 (exp)
       tree exp;
  {
    tree placement, init;
!   tree type, true_type, size, rval, t;
    tree full_type;
    tree outer_nelts = NULL_TREE;
    tree nelts = NULL_TREE;
!   tree alloc_call, alloc_expr, alloc_node;
    tree alloc_fn;
-   tree cookie_expr, init_expr;
    int has_array = 0;
    enum tree_code code;
    int nothrow, check_new;
    /* Nonzero if the user wrote `::new' rather than just `new'.  */
    int globally_qualified_p;
--- 2152,2179 ----
  static tree
  build_new_1 (exp)
       tree exp;
  {
    tree placement, init;
!   tree true_type, size, rval, t;
!   /* The type of the new-expression.  (This type is always a pointer
!      type.)  */
!   tree pointer_type;
!   /* The type pointed to by POINTER_TYPE.  */
!   tree type;
!   /* The type being allocated.  For "new T[...]" this will be an
!      ARRAY_TYPE.  */
    tree full_type;
+   /* A pointer type pointing to to the FULL_TYPE.  */
+   tree full_pointer_type;
    tree outer_nelts = NULL_TREE;
    tree nelts = NULL_TREE;
!   tree alloc_call, alloc_expr;
!   /* The address returned by the call to "operator new".  This node is
!      a VAR_DECL and is therefore reusable.  */
!   tree alloc_node;
    tree alloc_fn;
    int has_array = 0;
    enum tree_code code;
    int nothrow, check_new;
    /* Nonzero if the user wrote `::new' rather than just `new'.  */
    int globally_qualified_p;
*************** build_new_1 (exp)
*** 2173,2182 ****
--- 2184,2201 ----
    tree cookie_size = NULL_TREE;
    /* True if the function we are calling is a placement allocation
       function.  */
    bool placement_allocation_fn_p;
    tree args = NULL_TREE;
+   /* True if the storage must be initialized, either by a constructor
+      or due to an explicit new-intiailizer.  */
+   bool is_initialized;
+   /* The address of the thing allocated, not including any cookie.  In
+      particular, if an array cookie is in use, DATA_ADDR is the
+      address of the first array element.  This node is a VAR_DECL, and
+      is therefore reusable.  */
+   tree data_addr;
  
    placement = TREE_OPERAND (exp, 0);
    type = TREE_OPERAND (exp, 1);
    init = TREE_OPERAND (exp, 2);
    globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
*************** build_new_1 (exp)
*** 2216,2225 ****
--- 2235,2251 ----
      }
  
    if (abstract_virtuals_error (NULL_TREE, true_type))
      return error_mark_node;
  
+   is_initialized = (TYPE_NEEDS_CONSTRUCTING (type) || init);
+   if (CP_TYPE_CONST_P (true_type) && !is_initialized)
+     {
+       error ("uninitialized const in `new' of `%#T'", true_type);
+       return error_mark_node;
+     }
+ 
    size = size_in_bytes (true_type);
    if (has_array)
      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
  
    /* Allocate the object.  */
*************** build_new_1 (exp)
*** 2319,2366 ****
       So check for a null exception spec on the op new we just called.  */
  
    nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
    check_new = (flag_check_new || nothrow) && ! use_java_new;
  
!   alloc_expr = alloc_call;
! 
!   if (cookie_size)
!     /* Adjust so we're pointing to the start of the object.  */
!     alloc_expr = build (PLUS_EXPR, TREE_TYPE (alloc_expr),
! 			alloc_expr, cookie_size);
  
    /* While we're working, use a pointer to the type we've actually
!      allocated.  */
!   alloc_expr = convert (build_pointer_type (full_type), alloc_expr);
! 
!   /* Now save the allocation expression so we only evaluate it once.  */
!   alloc_expr = get_target_expr (alloc_expr);
    alloc_node = TREE_OPERAND (alloc_expr, 0);
  
-   /* Now initialize the cookie.  */
    if (cookie_size)
      {
        tree cookie;
  
        /* Store the number of bytes allocated so that we can know how
  	 many elements to destroy later.  We use the last sizeof
  	 (size_t) bytes to store the number of elements.  */
        cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
! 		      alloc_node, size_in_bytes (sizetype));
        cookie = build_indirect_ref (cookie, NULL);
  
!       cookie_expr = build (MODIFY_EXPR, void_type_node, cookie, nelts);
        TREE_SIDE_EFFECTS (cookie_expr) = 1;
      }
    else
!     cookie_expr = NULL_TREE;
  
    /* Now initialize the allocated object.  */
!   init_expr = NULL_TREE;
!   if (TYPE_NEEDS_CONSTRUCTING (type) || init)
      {
!       init_expr = build_indirect_ref (alloc_node, NULL);
  
        if (init == void_zero_node)
  	init = build_default_init (full_type, nelts);
        else if (init && pedantic && has_array)
  	pedwarn ("ISO C++ forbids initialization in array new");
--- 2345,2397 ----
       So check for a null exception spec on the op new we just called.  */
  
    nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
    check_new = (flag_check_new || nothrow) && ! use_java_new;
  
!   /* In the simple case, we can stop now.  */
!   pointer_type = build_pointer_type (type);
!   if (!cookie_size && !is_initialized)
!     return build_nop (pointer_type, alloc_call);
  
    /* While we're working, use a pointer to the type we've actually
!      allocated. Store the result of the call in a variable so that we
!      can use it more than once.  */
!   full_pointer_type = build_pointer_type (full_type);
!   alloc_expr = get_target_expr (build_nop (full_pointer_type, alloc_call));
    alloc_node = TREE_OPERAND (alloc_expr, 0);
+   rval = NULL_TREE;
  
    if (cookie_size)
      {
        tree cookie;
+       tree cookie_expr;
+ 
+       /* Adjust so we're pointing to the start of the object.  */
+       data_addr = get_target_expr (build (PLUS_EXPR, full_pointer_type,
+ 					  alloc_node, cookie_size));
  
        /* Store the number of bytes allocated so that we can know how
  	 many elements to destroy later.  We use the last sizeof
  	 (size_t) bytes to store the number of elements.  */
        cookie = build (MINUS_EXPR, build_pointer_type (sizetype),
! 		      data_addr, size_in_bytes (sizetype));
        cookie = build_indirect_ref (cookie, NULL);
  
!       cookie_expr = build (MODIFY_EXPR, sizetype, cookie, nelts);
        TREE_SIDE_EFFECTS (cookie_expr) = 1;
+       rval = build (COMPOUND_EXPR, void_type_node, data_addr, cookie_expr);
+       data_addr = TREE_OPERAND (data_addr, 0);
      }
    else
!     data_addr = alloc_node;
  
    /* Now initialize the allocated object.  */
!   if (is_initialized)
      {
!       tree init_expr;
! 
!       init_expr = build_indirect_ref (data_addr, NULL);
  
        if (init == void_zero_node)
  	init = build_default_init (full_type, nelts);
        else if (init && pedantic && has_array)
  	pedwarn ("ISO C++ forbids initialization in array new");
*************** build_new_1 (exp)
*** 2413,2438 ****
  	{
  	  enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
  	  tree cleanup;
  	  int flags = (LOOKUP_NORMAL 
  		       | (globally_qualified_p * LOOKUP_GLOBAL));
- 	  tree delete_node;
- 
- 	  if (cookie_size)
- 	    /* Subtract the padding back out to get to the pointer returned
- 	       from operator new.  */
- 	    delete_node = fold (build (MINUS_EXPR, TREE_TYPE (alloc_node),
- 				       alloc_node, cookie_size));
- 	  else
- 	    delete_node = alloc_node;
  
  	  /* The Standard is unclear here, but the right thing to do
!              is to use the same method for finding deallocation
!              functions that we use for finding allocation functions.  */
  	  flags |= LOOKUP_SPECULATIVELY;
  
! 	  cleanup = build_op_delete_call (dcode, delete_node, size, flags,
  					  (placement_allocation_fn_p 
  					   ? alloc_call : NULL_TREE));
  
  	  /* Ack!  First we allocate the memory.  Then we set our sentry
  	     variable to true, and expand a cleanup that deletes the memory
--- 2444,2460 ----
  	{
  	  enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
  	  tree cleanup;
  	  int flags = (LOOKUP_NORMAL 
  		       | (globally_qualified_p * LOOKUP_GLOBAL));
  
  	  /* The Standard is unclear here, but the right thing to do
! 	     is to use the same method for finding deallocation
! 	     functions that we use for finding allocation functions.  */
  	  flags |= LOOKUP_SPECULATIVELY;
  
! 	  cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
  					  (placement_allocation_fn_p 
  					   ? alloc_call : NULL_TREE));
  
  	  /* Ack!  First we allocate the memory.  Then we set our sentry
  	     variable to true, and expand a cleanup that deletes the memory
*************** build_new_1 (exp)
*** 2478,2521 ****
  		= build (COMPOUND_EXPR, void_type_node, begin,
  			 build (COMPOUND_EXPR, void_type_node, init_expr,
  				end));
  	    }
  	}
-     }
-   else if (CP_TYPE_CONST_P (true_type))
-     error ("uninitialized const in `new' of `%#T'", true_type);
  
!   /* Now build up the return value in reverse order.  */
  
!   rval = alloc_node;
  
!   if (init_expr)
!     rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_expr, rval);
!   if (cookie_expr)
!     rval = build (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval);
! 
!   if (rval == alloc_node)
!     /* If we didn't modify anything, strip the TARGET_EXPR and return the
!        (adjusted) call.  */
!     rval = TREE_OPERAND (alloc_expr, 1);
!   else
      {
!       if (check_new)
! 	{
! 	  tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
! 					   integer_zero_node);
! 	  rval = build_conditional_expr (ifexp, rval, alloc_node);
! 	}
! 
!       rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
      }
  
!   /* Now strip the outer ARRAY_TYPE, so we return a pointer to the first
!      element.  */
!   rval = convert (build_pointer_type (type), rval);
  
!   return rval;
  }
  
  static tree
  build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
       tree base, maxindex, type;
--- 2500,2530 ----
  		= build (COMPOUND_EXPR, void_type_node, begin,
  			 build (COMPOUND_EXPR, void_type_node, init_expr,
  				end));
  	    }
  	}
  
!       if (rval)
! 	rval = build (COMPOUND_EXPR, TREE_TYPE (init_expr), rval, init_expr);
!       else
! 	rval = init_expr;
!     }
  
!   rval = build (COMPOUND_EXPR, TREE_TYPE (alloc_node), rval, data_addr);
  
!   if (check_new)
      {
!       tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node, integer_zero_node);
!       rval = build_conditional_expr (ifexp, rval, alloc_node);
      }
  
!   /* Perform the allocation before anything else, so that ALLOC_NODE
!      has been initialized before we start using it.  */
!   rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
  
!   /* Convert to the final type.  */
!   return build_nop (pointer_type, rval);
  }
  
  static tree
  build_vec_delete_1 (base, maxindex, type, auto_delete_vec, use_global_delete)
       tree base, maxindex, type;
Index: testsuite/g++.dg/init/new5.C
===================================================================
RCS file: testsuite/g++.dg/init/new5.C
diff -N testsuite/g++.dg/init/new5.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/new5.C	13 Apr 2003 17:50:45 -0000
***************
*** 0 ****
--- 1,18 ----
+ // { dg-do run }
+ 
+ #include <new>
+     
+ void * operator new[](size_t, std::nothrow_t const &) throw()
+ { return NULL; }
+ 
+ struct X {
+     struct Inner { ~Inner() {} };
+ 
+     X() {
+       Inner * ic = new (std::nothrow) Inner[1]; // SegFault here
+     }
+ };
+ 
+ int main() {
+    X table;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]