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]

Re: C++ PATCH for c++/11309 (value-initialization in new)


Patch:
2008-07-31  Jason Merrill  <jason@redhat.com>

	PR c++/11309
	* tree.c (build_aggr_init_expr): Split out...
	(build_cplus_new): ...from here.
	(stabilize_init): Don't mess with AGGR_INIT_EXPR either.
	* init.c (build_new_1): new T() means value-initialization, 
	not default-initialization.
	(build_vec_init): Likewise.
	(build_value_init_1): Use build_aggr_init_expr.
	
dex: cp/typeck.c
===================================================================
*** cp/typeck.c	(revision 138354)
--- cp/typeck.c	(working copy)
*************** cp_build_modify_expr (tree lhs, enum tre
*** 6114,6120 ****
        from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
  		   ? 1 + (modifycode != INIT_EXPR): 0;
        return build_vec_init (lhs, NULL_TREE, newrhs,
! 			     /*explicit_default_init_p=*/false,
  			     from_array, complain);
      }
  
--- 6114,6120 ----
        from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
  		   ? 1 + (modifycode != INIT_EXPR): 0;
        return build_vec_init (lhs, NULL_TREE, newrhs,
! 			     /*explicit_value_init_p=*/false,
  			     from_array, complain);
      }
  
Index: cp/init.c
===================================================================
*** cp/init.c	(revision 138354)
--- cp/init.c	(working copy)
*************** build_value_init_1 (tree type, bool have
*** 347,353 ****
    if (CLASS_TYPE_P (type))
      {
        if (type_has_user_provided_constructor (type) && !have_ctor)
! 	return build_cplus_new
  	  (type,
  	   build_special_member_call (NULL_TREE, complete_ctor_identifier,
  				      NULL_TREE, type, LOOKUP_NORMAL,
--- 347,353 ----
    if (CLASS_TYPE_P (type))
      {
        if (type_has_user_provided_constructor (type) && !have_ctor)
! 	return build_aggr_init_expr
  	  (type,
  	   build_special_member_call (NULL_TREE, complete_ctor_identifier,
  				      NULL_TREE, type, LOOKUP_NORMAL,
*************** perform_member_init (tree member, tree i
*** 511,517 ****
  	{
  	  /* Initialization of one array from another.  */
  	  finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
! 					    /*explicit_default_init_p=*/false,
  					    /* from_array=*/1,
                                              tf_warning_or_error));
  	}
--- 511,517 ----
  	{
  	  /* Initialization of one array from another.  */
  	  finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
! 					    /*explicit_value_init_p=*/false,
  					    /* from_array=*/1,
                                              tf_warning_or_error));
  	}
*************** build_aggr_init (tree exp, tree init, in
*** 1286,1292 ****
        if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
  	itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
        stmt_expr = build_vec_init (exp, NULL_TREE, init,
! 				  /*explicit_default_init_p=*/false,
  				  itype && same_type_p (itype,
  							TREE_TYPE (exp)),
                                    complain);
--- 1286,1292 ----
        if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
  	itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
        stmt_expr = build_vec_init (exp, NULL_TREE, init,
! 				  /*explicit_value_init_p=*/false,
  				  itype && same_type_p (itype,
  							TREE_TYPE (exp)),
                                    complain);
*************** build_new_1 (tree placement, tree type, 
*** 2154,2172 ****
    if (is_initialized)
      {
        bool stable;
  
        init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
  
!       if (array_p)
  	{
! 	  bool explicit_default_init_p = false;
  
! 	  if (init == void_zero_node)
! 	    {
! 	      init = NULL_TREE;
! 	      explicit_default_init_p = true;
! 	    }
! 	  else if (init)
              {
                if (complain & tf_error)
                  permerror ("ISO C++ forbids initialization in array new");
--- 2154,2172 ----
    if (is_initialized)
      {
        bool stable;
+       bool explicit_value_init_p = false;
  
        init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
  
!       if (init == void_zero_node)
  	{
! 	  init = NULL_TREE;
! 	  explicit_value_init_p = true;
! 	}
  
!       if (array_p)
! 	{
! 	  if (init)
              {
                if (complain & tf_error)
                  permerror ("ISO C++ forbids initialization in array new");
*************** build_new_1 (tree placement, tree type, 
*** 2179,2185 ****
  						  integer_one_node,
  						  complain),
  			      init,
! 			      explicit_default_init_p,
  			      /*from_array=*/0,
                                complain);
  
--- 2179,2185 ----
  						  integer_one_node,
  						  complain),
  			      init,
! 			      explicit_value_init_p,
  			      /*from_array=*/0,
                                complain);
  
*************** build_new_1 (tree placement, tree type, 
*** 2190,2206 ****
  	}
        else
  	{
! 	  if (init == void_zero_node)
! 	    init = build_default_init (full_type, nelts);
! 
! 	  if (TYPE_NEEDS_CONSTRUCTING (type))
  	    {
  	      init_expr = build_special_member_call (init_expr,
  						     complete_ctor_identifier,
  						     init, elt_type,
  						     LOOKUP_NORMAL,
                                                       complain);
! 	      stable = stabilize_init (init_expr, &init_preeval_expr);
  	    }
  	  else
  	    {
--- 2190,2208 ----
  	}
        else
  	{
! 	  if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
  	    {
  	      init_expr = build_special_member_call (init_expr,
  						     complete_ctor_identifier,
  						     init, elt_type,
  						     LOOKUP_NORMAL,
                                                       complain);
! 	    }
! 	  else if (explicit_value_init_p)
! 	    {
! 	      /* Something like `new int()'.  */
! 	      init_expr = build2 (INIT_EXPR, full_type,
! 				  init_expr, build_value_init (full_type));
  	    }
  	  else
  	    {
*************** build_new_1 (tree placement, tree type, 
*** 2216,2223 ****
  
  	      init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
  						complain);
- 	      stable = stabilize_init (init_expr, &init_preeval_expr);
  	    }
  	}
  
        if (init_expr == error_mark_node)
--- 2218,2225 ----
  
  	      init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
  						complain);
  	    }
+ 	  stable = stabilize_init (init_expr, &init_preeval_expr);
  	}
  
        if (init_expr == error_mark_node)
*************** get_temp_regvar (tree type, tree init)
*** 2662,2669 ****
  
     INIT is the (possibly NULL) initializer.
  
!    If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL.  All
!    elements in the array are default-initialized.
  
     FROM_ARRAY is 0 if we should init everything with INIT
     (i.e., every element initialized from INIT).
--- 2664,2671 ----
  
     INIT is the (possibly NULL) initializer.
  
!    If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL.  All
!    elements in the array are value-initialized.
  
     FROM_ARRAY is 0 if we should init everything with INIT
     (i.e., every element initialized from INIT).
*************** get_temp_regvar (tree type, tree init)
*** 2674,2680 ****
  
  tree
  build_vec_init (tree base, tree maxindex, tree init,
! 		bool explicit_default_init_p,
  		int from_array, tsubst_flags_t complain)
  {
    tree rval;
--- 2676,2682 ----
  
  tree
  build_vec_init (tree base, tree maxindex, tree init,
! 		bool explicit_value_init_p,
  		int from_array, tsubst_flags_t complain)
  {
    tree rval;
*************** build_vec_init (tree base, tree maxindex
*** 2704,2710 ****
    if (maxindex == NULL_TREE || maxindex == error_mark_node)
      return error_mark_node;
  
!   if (explicit_default_init_p)
      gcc_assert (!init);
  
    inner_elt_type = strip_array_types (atype);
--- 2706,2712 ----
    if (maxindex == NULL_TREE || maxindex == error_mark_node)
      return error_mark_node;
  
!   if (explicit_value_init_p)
      gcc_assert (!init);
  
    inner_elt_type = strip_array_types (atype);
*************** build_vec_init (tree base, tree maxindex
*** 2840,2846 ****
       We do need to keep going if we're copying an array.  */
  
    if (from_array
!       || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p)
  	  && ! (host_integerp (maxindex, 0)
  		&& (num_initialized_elts
  		    == tree_low_cst (maxindex, 0) + 1))))
--- 2842,2848 ----
       We do need to keep going if we're copying an array.  */
  
    if (from_array
!       || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
  	  && ! (host_integerp (maxindex, 0)
  		&& (num_initialized_elts
  		    == tree_low_cst (maxindex, 0) + 1))))
*************** build_vec_init (tree base, tree maxindex
*** 2889,2905 ****
  	      ("cannot initialize multi-dimensional array with initializer");
  	  elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
  				     0, 0,
! 				     /*explicit_default_init_p=*/false,
  				     0, complain);
  	}
!       else if (!TYPE_NEEDS_CONSTRUCTING (type))
! 	elt_init = (cp_build_modify_expr
! 		    (to, INIT_EXPR,
! 		     build_zero_init (type, size_one_node,
! 				      /*static_storage_p=*/false),
! 		     complain));
        else
! 	elt_init = build_aggr_init (to, init, 0, complain);
  
        current_stmt_tree ()->stmts_are_full_exprs_p = 1;
        finish_expr_stmt (elt_init);
--- 2891,2907 ----
  	      ("cannot initialize multi-dimensional array with initializer");
  	  elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
  				     0, 0,
! 				     explicit_value_init_p,
  				     0, complain);
  	}
!       else if (explicit_value_init_p)
! 	elt_init = build2 (INIT_EXPR, type, to,
! 			   build_value_init (type));
        else
! 	{
! 	  gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
! 	  elt_init = build_aggr_init (to, init, 0, complain);
! 	}
  
        current_stmt_tree ()->stmts_are_full_exprs_p = 1;
        finish_expr_stmt (elt_init);
Index: cp/tree.c
===================================================================
*** cp/tree.c	(revision 138354)
--- cp/tree.c	(working copy)
*************** build_aggr_init_array (tree return_type,
*** 339,353 ****
  }
  
  /* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
!    target.  TYPE is the type that this initialization should appear to
!    have.
  
!    Build an encapsulation of the initialization to perform
!    and return it so that it can be processed by language-independent
!    and language-specific expression expanders.  */
  
  tree
! build_cplus_new (tree type, tree init)
  {
    tree fn;
    tree slot;
--- 339,355 ----
  }
  
  /* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
!    target.  TYPE is the type to be initialized.
  
!    Build an AGGR_INIT_EXPR to represent the initialization.  This function
!    differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
!    to initialize another object, whereas a TARGET_EXPR can either
!    initialize another object or create its own temporary object, and as a
!    result building up a TARGET_EXPR requires that the type's destructor be
!    callable.  */
  
  tree
! build_aggr_init_expr (tree type, tree init)
  {
    tree fn;
    tree slot;
*************** build_cplus_new (tree type, tree init)
*** 369,376 ****
  	     && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
  	     && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
  
-   slot = build_local_temp (type);
- 
    /* We split the CALL_EXPR into its function and its arguments here.
       Then, in expand_expr, we put them back together.  The reason for
       this is that this expression might be a default argument
--- 371,376 ----
*************** build_cplus_new (tree type, tree init)
*** 384,389 ****
--- 384,391 ----
       type, don't mess with AGGR_INIT_EXPR.  */
    if (is_ctor || TREE_ADDRESSABLE (type))
      {
+       slot = build_local_temp (type);
+ 
        if (TREE_CODE(init) == CALL_EXPR)
  	rval = build_aggr_init_array (void_type_node, fn, slot,
  				      call_expr_nargs (init),
*************** build_cplus_new (tree type, tree init)
*** 398,403 ****
--- 400,429 ----
    else
      rval = init;
  
+   return rval;
+ }
+ 
+ /* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+    target.  TYPE is the type that this initialization should appear to
+    have.
+ 
+    Build an encapsulation of the initialization to perform
+    and return it so that it can be processed by language-independent
+    and language-specific expression expanders.  */
+ 
+ tree
+ build_cplus_new (tree type, tree init)
+ {
+   tree rval = build_aggr_init_expr (type, init);
+   tree slot;
+ 
+   if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+     slot = AGGR_INIT_EXPR_SLOT (rval);
+   else if (TREE_CODE (rval) == CALL_EXPR)
+     slot = build_local_temp (type);
+   else
+     return rval;
+ 
    rval = build_target_expr (slot, rval);
    TARGET_EXPR_IMPLICIT_P (rval) = 1;
  
*************** stabilize_init (tree init, tree *initp)
*** 2687,2693 ****
      return true;
  
    if (TREE_CODE (t) == INIT_EXPR
!       && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
      {
        TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
        return true;
--- 2713,2720 ----
      return true;
  
    if (TREE_CODE (t) == INIT_EXPR
!       && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
!       && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
      {
        TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
        return true;
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h	(revision 138354)
--- cp/cp-tree.h	(working copy)
*************** extern tree build_min_nt			(enum tree_co
*** 4742,4747 ****
--- 4742,4748 ----
  extern tree build_min_non_dep			(enum tree_code, tree, ...);
  extern tree build_min_non_dep_call_list		(tree, tree, tree);
  extern tree build_cplus_new			(tree, tree);
+ extern tree build_aggr_init_expr		(tree, tree);
  extern tree get_target_expr			(tree);
  extern tree build_cplus_array_type		(tree, tree);
  extern tree build_array_of_n_type		(tree, int);
Index: testsuite/g++.dg/tree-ssa/pr31146-2.C
===================================================================
*** testsuite/g++.dg/tree-ssa/pr31146-2.C	(revision 138354)
--- testsuite/g++.dg/tree-ssa/pr31146-2.C	(working copy)
*************** double foo (void)
*** 20,24 ****
    return v.a[2];
  }
  
! /* { dg-final { scan-tree-dump "Replaced .*iftmp.* != 0B. with .1" "forwprop1" } } */
  /* { dg-final { cleanup-tree-dump "forwprop1" } } */
--- 20,24 ----
    return v.a[2];
  }
  
! /* { dg-final { scan-tree-dump "Replaced .* != 0B. with .1" "forwprop1" } } */
  /* { dg-final { cleanup-tree-dump "forwprop1" } } */
Index: testsuite/g++.dg/lookup/new1.C
===================================================================
*** testsuite/g++.dg/lookup/new1.C	(revision 138354)
--- testsuite/g++.dg/lookup/new1.C	(working copy)
***************
*** 4,13 ****
  
  int main() {
    int i;
!   void* operator new(unsigned s, int* p);
    int* e = new(&i) int;                    // { dg-error "no matching function" }
    int* f = new int;
    return 0;
  }
  
! // { dg-excess-errors "operator new" }
--- 4,13 ----
  
  int main() {
    int i;
!   void* operator new(__SIZE_TYPE__ s, int* p);
    int* e = new(&i) int;                    // { dg-error "no matching function" }
    int* f = new int;
    return 0;
  }
  
! // { dg-error "candidate" "" { target *-*-* } 0 }
Index: testsuite/g++.dg/expr/anew4.C
===================================================================
*** testsuite/g++.dg/expr/anew4.C	(revision 138354)
--- testsuite/g++.dg/expr/anew4.C	(working copy)
***************
*** 1,5 ****
! // { dg-do run { xfail *-*-* } }
! // XFAILed until PR2123 is fixed
  // PR 11228: array operator new, with zero-initialization and a variable sized array.
  // Regression test for PR 
  // Author: Matt Austern <austern@apple.com>
--- 1,4 ----
! // { dg-do run }
  // PR 11228: array operator new, with zero-initialization and a variable sized array.
  // Regression test for PR 
  // Author: Matt Austern <austern@apple.com>
Index: testsuite/g++.dg/init/value3.C
===================================================================
*** testsuite/g++.dg/init/value3.C	(revision 0)
--- testsuite/g++.dg/init/value3.C	(revision 0)
***************
*** 0 ****
--- 1,31 ----
+ // Testcase for value-initialization in new-expressions.
+ // { dg-do run }
+ 
+ #include <stdlib.h>
+ #include <string.h>
+ 
+ // Make sure that we return memory that isn't already set to 0.
+ void *operator new(size_t s)
+ {
+   void *p = malloc (s);
+   memset (p, 42, s);
+   return p;
+ }
+ 
+ struct A { A() {} ~A() {} };
+ struct B { A a; int i; };
+ 
+ int main()
+ {
+   B *p = new B();
+   if (p->i != 0)
+     abort();
+ 
+   p = new B[2]();
+   if (p[0].i != 0 || p[1].i != 0)
+     abort();
+ 
+   B(*p2)[2] = new B[2][2]();
+   if (p2[0][0].i != 0 || p2[0][1].i != 0)
+     abort();
+ }

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