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 18369


When reorganizing some of build_new_1, I failed to correctly handle
the case of array type like "new (int[5])" -- although the code did
still handle the unparenthesized form.  I've fixed that problem and
tidied up the code a bit.

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

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-11-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18369
	* init.c (build_new_1): Handle parenthesized type-ids that name an
	array type.  Tidy.

2004-11-09  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18369
	* g++.dg/init/new12.C: New test.

Index: testsuite/g++.dg/init/new12.C
===================================================================
RCS file: testsuite/g++.dg/init/new12.C
diff -N testsuite/g++.dg/init/new12.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/new12.C	9 Nov 2004 22:56:44 -0000
***************
*** 0 ****
--- 1,6 ----
+ // PR c++/18369
+ 
+ void breakme () 
+ {
+   int *v = new (int [5]);
+ }
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.400
diff -c -5 -p -r1.400 init.c
*** cp/init.c	11 Oct 2004 15:38:22 -0000	1.400
--- cp/init.c	9 Nov 2004 22:56:44 -0000
*************** build_java_class_ref (tree type)
*** 1716,1746 ****
  
  static tree
  build_new_1 (tree exp)
  {
    tree placement, init;
!   tree true_type, size, rval;
    /* 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;
    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;
    int use_java_new = 0;
    /* If non-NULL, the number of extra bytes to allocate at the
--- 1716,1758 ----
  
  static tree
  build_new_1 (tree exp)
  {
    tree placement, init;
!   tree size, rval;
!   /* True iff this is a call to "operator new[]" instead of just
!      "operator new".  */   
!   bool array_p = false;
!   /* True iff ARRAY_P is true and the bound of the array type is
!      not necessarily a compile time constant.  For example, VLA_P is
!      true for "new int[f()]".  */
!   bool vla_p = false;
!   /* The type being allocated.  If ARRAY_P is true, this will be an 
!      ARRAY_TYPE.  */
!   tree full_type;
!   /* If ARRAY_P is true, the element type of the array.  This is an
!      never ARRAY_TYPE; for something like "new int[3][4]", the
!      ELT_TYPE is "int".  If ARRAY_P is false, this is the same type as
!      FULL_TYPE.  */
!   tree elt_type;
    /* The type of the new-expression.  (This type is always a pointer
       type.)  */
    tree pointer_type;
!   /* The type pointed to by POINTER_TYPE.  This type may be different
!      from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an
!      ARRAY_TYPE, but TYPE may be an ARRAY_TYPE.  */
    tree 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;
    tree cookie_expr, init_expr;
    int nothrow, check_new;
    /* Nonzero if the user wrote `::new' rather than just `new'.  */
    int globally_qualified_p;
    int use_java_new = 0;
    /* If non-NULL, the number of extra bytes to allocate at the
*************** build_new_1 (tree exp)
*** 1769,1848 ****
  
    if (nelts)
      {
        tree index;
  
-       has_array = 1;
        outer_nelts = nelts;
  
        /* ??? The middle-end will error on us for building a VLA outside a 
  	 function context.  Methinks that's not it's purvey.  So we'll do
  	 our own VLA layout later.  */
! 
        full_type = build_cplus_array_type (type, NULL_TREE);
- 
        index = convert (sizetype, nelts);
        index = size_binop (MINUS_EXPR, index, size_one_node);
        TYPE_DOMAIN (full_type) = build_index_type (index);
      }
    else
!     full_type = type;
! 
!   true_type = type;
! 
!   code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
  
    /* If our base type is an array, then make sure we know how many elements
       it has.  */
!   while (TREE_CODE (true_type) == ARRAY_TYPE)
!     {
!       tree this_nelts = array_type_nelts_top (true_type);
!       nelts = cp_build_binary_op (MULT_EXPR, nelts, this_nelts);
!       true_type = TREE_TYPE (true_type);
!     }
  
!   if (!complete_type_or_else (true_type, exp))
      return error_mark_node;
  
!   if (TREE_CODE (true_type) == VOID_TYPE)
      {
        error ("invalid type %<void%> for new");
        return error_mark_node;
      }
  
!   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 %q#T", true_type);
        return error_mark_node;
      }
  
!   size = size_in_bytes (true_type);
!   if (has_array)
      {
!       tree n, bitsize;
! 
!       /* Do our own VLA layout.  Setting TYPE_SIZE/_UNIT is necessary in
! 	 order for the <INIT_EXPR <*foo> <CONSTRUCTOR ...>> to be valid.  */
! 
!       n = convert (sizetype, nelts);
!       size = size_binop (MULT_EXPR, size, n);
!       TYPE_SIZE_UNIT (full_type) = size;
  
!       n = convert (bitsizetype, nelts);
!       bitsize = size_binop (MULT_EXPR, TYPE_SIZE (true_type), n);
!       TYPE_SIZE (full_type) = bitsize;
      }
  
    /* Allocate the object.  */
!   if (! placement && TYPE_FOR_JAVA (true_type))
      {
        tree class_addr, alloc_decl;
!       tree class_decl = build_java_class_ref (true_type);
        static const char alloc_name[] = "_Jv_AllocObject";
  
        use_java_new = 1;
        alloc_decl = NULL;
        if (!get_global_value_if_present (get_identifier (alloc_name), 
--- 1781,1864 ----
  
    if (nelts)
      {
        tree index;
  
        outer_nelts = nelts;
+       array_p = true;
  
        /* ??? The middle-end will error on us for building a VLA outside a 
  	 function context.  Methinks that's not it's purvey.  So we'll do
  	 our own VLA layout later.  */
!       vla_p = true;
        full_type = build_cplus_array_type (type, NULL_TREE);
        index = convert (sizetype, nelts);
        index = size_binop (MINUS_EXPR, index, size_one_node);
        TYPE_DOMAIN (full_type) = build_index_type (index);
      }
    else
!     {
!       full_type = type;
!       if (TREE_CODE (type) == ARRAY_TYPE)
! 	{
! 	  array_p = true;
! 	  nelts = array_type_nelts_top (type);
! 	  outer_nelts = nelts;
! 	  type = TREE_TYPE (type);
! 	}
!     }
  
    /* If our base type is an array, then make sure we know how many elements
       it has.  */
!   for (elt_type = type;
!        TREE_CODE (elt_type) == ARRAY_TYPE;
!        elt_type = TREE_TYPE (elt_type))
!     nelts = cp_build_binary_op (MULT_EXPR, nelts, 
! 				array_type_nelts_top (elt_type));
  
!   if (!complete_type_or_else (elt_type, exp))
      return error_mark_node;
  
!   if (TREE_CODE (elt_type) == VOID_TYPE)
      {
        error ("invalid type %<void%> for new");
        return error_mark_node;
      }
  
!   if (abstract_virtuals_error (NULL_TREE, elt_type))
      return error_mark_node;
  
!   is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
!   if (CP_TYPE_CONST_P (elt_type) && !is_initialized)
      {
!       error ("uninitialized const in %<new%> of %q#T", elt_type);
        return error_mark_node;
      }
  
!   size = size_in_bytes (elt_type);
!   if (array_p)
      {
!       size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
!       if (vla_p)
! 	{
! 	  tree n, bitsize;
  
! 	  /* Do our own VLA layout.  Setting TYPE_SIZE/_UNIT is
! 	     necessary in order for the <INIT_EXPR <*foo> <CONSTRUCTOR
! 	     ...>> to be valid.  */
! 	  TYPE_SIZE_UNIT (full_type) = size;
! 	  n = convert (bitsizetype, nelts);
! 	  bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n);
! 	  TYPE_SIZE (full_type) = bitsize;
! 	}
      }
  
    /* Allocate the object.  */
!   if (! placement && TYPE_FOR_JAVA (elt_type))
      {
        tree class_addr, alloc_decl;
!       tree class_decl = build_java_class_ref (elt_type);
        static const char alloc_name[] = "_Jv_AllocObject";
  
        use_java_new = 1;
        alloc_decl = NULL;
        if (!get_global_value_if_present (get_identifier (alloc_name), 
*************** build_new_1 (tree exp)
*** 1865,1910 ****
    else
      {
        tree fnname;
        tree fns;
  
!       fnname = ansi_opname (code);
  
        if (!globally_qualified_p 
! 	  && CLASS_TYPE_P (true_type)
! 	  && (has_array
! 	      ? TYPE_HAS_ARRAY_NEW_OPERATOR (true_type)
! 	      : TYPE_HAS_NEW_OPERATOR (true_type)))
  	{
  	  /* Use a class-specific operator new.  */
  	  /* If a cookie is required, add some extra space.  */
! 	  if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
  	    {
! 	      cookie_size = targetm.cxx.get_cookie_size (true_type);
  	      size = size_binop (PLUS_EXPR, size, cookie_size);
  	    }
  	  /* Create the argument list.  */
  	  args = tree_cons (NULL_TREE, size, placement);
  	  /* Do name-lookup to find the appropriate operator.  */
! 	  fns = lookup_fnfields (true_type, fnname, /*protect=*/2);
  	  if (TREE_CODE (fns) == TREE_LIST)
  	    {
  	      error ("request for member %qD is ambiguous", fnname);
  	      print_candidates (fns);
  	      return error_mark_node;
  	    }
! 	  alloc_call = build_new_method_call (build_dummy_object (true_type),
  					      fns, args,
  					      /*conversion_path=*/NULL_TREE,
  					      LOOKUP_NORMAL);
  	}
        else
  	{
  	  /* Use a global operator new.  */
  	  /* See if a cookie might be required.  */
! 	  if (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
! 	    cookie_size = targetm.cxx.get_cookie_size (true_type);
  	  else
  	    cookie_size = NULL_TREE;
  
  	  alloc_call = build_operator_new_call (fnname, placement, 
  						&size, &cookie_size);
--- 1881,1926 ----
    else
      {
        tree fnname;
        tree fns;
  
!       fnname = ansi_opname (array_p ? VEC_NEW_EXPR : NEW_EXPR);
  
        if (!globally_qualified_p 
! 	  && CLASS_TYPE_P (elt_type)
! 	  && (array_p
! 	      ? TYPE_HAS_ARRAY_NEW_OPERATOR (elt_type)
! 	      : TYPE_HAS_NEW_OPERATOR (elt_type)))
  	{
  	  /* Use a class-specific operator new.  */
  	  /* If a cookie is required, add some extra space.  */
! 	  if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
  	    {
! 	      cookie_size = targetm.cxx.get_cookie_size (elt_type);
  	      size = size_binop (PLUS_EXPR, size, cookie_size);
  	    }
  	  /* Create the argument list.  */
  	  args = tree_cons (NULL_TREE, size, placement);
  	  /* Do name-lookup to find the appropriate operator.  */
! 	  fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
  	  if (TREE_CODE (fns) == TREE_LIST)
  	    {
  	      error ("request for member %qD is ambiguous", fnname);
  	      print_candidates (fns);
  	      return error_mark_node;
  	    }
! 	  alloc_call = build_new_method_call (build_dummy_object (elt_type),
  					      fns, args,
  					      /*conversion_path=*/NULL_TREE,
  					      LOOKUP_NORMAL);
  	}
        else
  	{
  	  /* Use a global operator new.  */
  	  /* See if a cookie might be required.  */
! 	  if (array_p && TYPE_VEC_NEW_USES_COOKIE (elt_type))
! 	    cookie_size = targetm.cxx.get_cookie_size (elt_type);
  	  else
  	    cookie_size = NULL_TREE;
  
  	  alloc_call = build_operator_new_call (fnname, placement, 
  						&size, &cookie_size);
*************** build_new_1 (tree exp)
*** 1993,2003 ****
  	  /* Also store the element size.  */
  	  cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype),
  			       cookie_ptr, size_in_bytes (sizetype));
  	  cookie = build_indirect_ref (cookie_ptr, NULL);
  	  cookie = build2 (MODIFY_EXPR, sizetype, cookie,
! 			   size_in_bytes(true_type));
  	  cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
  				cookie, cookie_expr);
  	}
        data_addr = TARGET_EXPR_SLOT (data_addr);
      }
--- 2009,2019 ----
  	  /* Also store the element size.  */
  	  cookie_ptr = build2 (MINUS_EXPR, build_pointer_type (sizetype),
  			       cookie_ptr, size_in_bytes (sizetype));
  	  cookie = build_indirect_ref (cookie_ptr, NULL);
  	  cookie = build2 (MODIFY_EXPR, sizetype, cookie,
! 			   size_in_bytes(elt_type));
  	  cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
  				cookie, cookie_expr);
  	}
        data_addr = TARGET_EXPR_SLOT (data_addr);
      }
*************** build_new_1 (tree exp)
*** 2018,2031 ****
  
        init_expr = build_indirect_ref (data_addr, NULL);
  
        if (init == void_zero_node)
  	init = build_default_init (full_type, nelts);
!       else if (init && has_array)
  	pedwarn ("ISO C++ forbids initialization in array new");
  
!       if (has_array)
  	{
  	  init_expr
  	    = build_vec_init (init_expr,
  			      cp_build_binary_op (MINUS_EXPR, outer_nelts,
  						  integer_one_node),
--- 2034,2047 ----
  
        init_expr = build_indirect_ref (data_addr, NULL);
  
        if (init == void_zero_node)
  	init = build_default_init (full_type, nelts);
!       else if (init && array_p)
  	pedwarn ("ISO C++ forbids initialization in array new");
  
!       if (array_p)
  	{
  	  init_expr
  	    = build_vec_init (init_expr,
  			      cp_build_binary_op (MINUS_EXPR, outer_nelts,
  						  integer_one_node),
*************** build_new_1 (tree exp)
*** 2038,2048 ****
  	}
        else if (TYPE_NEEDS_CONSTRUCTING (type))
  	{
  	  init_expr = build_special_member_call (init_expr, 
  						 complete_ctor_identifier,
! 						 init, true_type,
  						 LOOKUP_NORMAL);
  	  stable = stabilize_init (init_expr, &init_preeval_expr);
  	}
        else
  	{
--- 2054,2064 ----
  	}
        else if (TYPE_NEEDS_CONSTRUCTING (type))
  	{
  	  init_expr = build_special_member_call (init_expr, 
  						 complete_ctor_identifier,
! 						 init, elt_type,
  						 LOOKUP_NORMAL);
  	  stable = stabilize_init (init_expr, &init_preeval_expr);
  	}
        else
  	{
*************** build_new_1 (tree exp)
*** 2071,2081 ****
  	 unambiguous matching deallocation function can be found,
  	 propagating the exception does not cause the object's memory to be
  	 freed.  */
        if (flag_exceptions && ! use_java_new)
  	{
! 	  enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
  	  tree cleanup;
  
  	  /* 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.  */
--- 2087,2097 ----
  	 unambiguous matching deallocation function can be found,
  	 propagating the exception does not cause the object's memory to be
  	 freed.  */
        if (flag_exceptions && ! use_java_new)
  	{
! 	  enum tree_code dcode = array_p ? VEC_DELETE_EXPR : DELETE_EXPR;
  	  tree cleanup;
  
  	  /* 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.  */


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