This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/11309 (value-initialization in new)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 31 Jul 2008 01:06:40 -0400
- Subject: Re: C++ PATCH for c++/11309 (value-initialization in new)
- References: <4891484F.2030504@redhat.com>
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();
+ }