Commit 844ae01d by Jason Merrill Committed by Jason Merrill

re PR c++/11309 (Testsuite failures in g++.dg/expr/anew1.C (and anew2.C anew3.C anew4.c))

        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.

From-SVN: r138355
parent 636b71b9
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.
2008-07-30 Dodji Seketeli <dseketel@redhat.com> 2008-07-30 Dodji Seketeli <dseketel@redhat.com>
PR c++/36767 PR c++/36767
......
...@@ -4742,6 +4742,7 @@ extern tree build_min_nt (enum tree_code, ...); ...@@ -4742,6 +4742,7 @@ extern tree build_min_nt (enum tree_code, ...);
extern tree build_min_non_dep (enum tree_code, tree, ...); extern tree build_min_non_dep (enum tree_code, tree, ...);
extern tree build_min_non_dep_call_list (tree, tree, tree); extern tree build_min_non_dep_call_list (tree, tree, tree);
extern tree build_cplus_new (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 get_target_expr (tree);
extern tree build_cplus_array_type (tree, tree); extern tree build_cplus_array_type (tree, tree);
extern tree build_array_of_n_type (tree, int); extern tree build_array_of_n_type (tree, int);
......
...@@ -347,7 +347,7 @@ build_value_init_1 (tree type, bool have_ctor) ...@@ -347,7 +347,7 @@ build_value_init_1 (tree type, bool have_ctor)
if (CLASS_TYPE_P (type)) if (CLASS_TYPE_P (type))
{ {
if (type_has_user_provided_constructor (type) && !have_ctor) if (type_has_user_provided_constructor (type) && !have_ctor)
return build_cplus_new return build_aggr_init_expr
(type, (type,
build_special_member_call (NULL_TREE, complete_ctor_identifier, build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL_TREE, type, LOOKUP_NORMAL, NULL_TREE, type, LOOKUP_NORMAL,
...@@ -511,7 +511,7 @@ perform_member_init (tree member, tree init) ...@@ -511,7 +511,7 @@ perform_member_init (tree member, tree init)
{ {
/* Initialization of one array from another. */ /* Initialization of one array from another. */
finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init), finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
/*explicit_default_init_p=*/false, /*explicit_value_init_p=*/false,
/* from_array=*/1, /* from_array=*/1,
tf_warning_or_error)); tf_warning_or_error));
} }
...@@ -1286,7 +1286,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) ...@@ -1286,7 +1286,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED) if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
stmt_expr = build_vec_init (exp, NULL_TREE, init, stmt_expr = build_vec_init (exp, NULL_TREE, init,
/*explicit_default_init_p=*/false, /*explicit_value_init_p=*/false,
itype && same_type_p (itype, itype && same_type_p (itype,
TREE_TYPE (exp)), TREE_TYPE (exp)),
complain); complain);
...@@ -2154,19 +2154,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, ...@@ -2154,19 +2154,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
if (is_initialized) if (is_initialized)
{ {
bool stable; bool stable;
bool explicit_value_init_p = false;
init_expr = cp_build_indirect_ref (data_addr, NULL, complain); init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
if (array_p)
{
bool explicit_default_init_p = false;
if (init == void_zero_node) if (init == void_zero_node)
{ {
init = NULL_TREE; init = NULL_TREE;
explicit_default_init_p = true; explicit_value_init_p = true;
} }
else if (init)
if (array_p)
{
if (init)
{ {
if (complain & tf_error) if (complain & tf_error)
permerror ("ISO C++ forbids initialization in array new"); permerror ("ISO C++ forbids initialization in array new");
...@@ -2179,7 +2179,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, ...@@ -2179,7 +2179,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
integer_one_node, integer_one_node,
complain), complain),
init, init,
explicit_default_init_p, explicit_value_init_p,
/*from_array=*/0, /*from_array=*/0,
complain); complain);
...@@ -2190,17 +2190,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, ...@@ -2190,17 +2190,19 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
} }
else else
{ {
if (init == void_zero_node) if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
init = build_default_init (full_type, nelts);
if (TYPE_NEEDS_CONSTRUCTING (type))
{ {
init_expr = build_special_member_call (init_expr, init_expr = build_special_member_call (init_expr,
complete_ctor_identifier, complete_ctor_identifier,
init, elt_type, init, elt_type,
LOOKUP_NORMAL, LOOKUP_NORMAL,
complain); complain);
stable = stabilize_init (init_expr, &init_preeval_expr); }
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 else
{ {
...@@ -2216,8 +2218,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, ...@@ -2216,8 +2218,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init, init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
complain); complain);
stable = stabilize_init (init_expr, &init_preeval_expr);
} }
stable = stabilize_init (init_expr, &init_preeval_expr);
} }
if (init_expr == error_mark_node) if (init_expr == error_mark_node)
...@@ -2662,8 +2664,8 @@ get_temp_regvar (tree type, tree init) ...@@ -2662,8 +2664,8 @@ get_temp_regvar (tree type, tree init)
INIT is the (possibly NULL) initializer. INIT is the (possibly NULL) initializer.
If EXPLICIT_DEFAULT_INIT_P is true, then INIT must be NULL. All If EXPLICIT_VALUE_INIT_P is true, then INIT must be NULL. All
elements in the array are default-initialized. elements in the array are value-initialized.
FROM_ARRAY is 0 if we should init everything with INIT FROM_ARRAY is 0 if we should init everything with INIT
(i.e., every element initialized from INIT). (i.e., every element initialized from INIT).
...@@ -2674,7 +2676,7 @@ get_temp_regvar (tree type, tree init) ...@@ -2674,7 +2676,7 @@ get_temp_regvar (tree type, tree init)
tree tree
build_vec_init (tree base, tree maxindex, tree init, build_vec_init (tree base, tree maxindex, tree init,
bool explicit_default_init_p, bool explicit_value_init_p,
int from_array, tsubst_flags_t complain) int from_array, tsubst_flags_t complain)
{ {
tree rval; tree rval;
...@@ -2704,7 +2706,7 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -2704,7 +2706,7 @@ build_vec_init (tree base, tree maxindex, tree init,
if (maxindex == NULL_TREE || maxindex == error_mark_node) if (maxindex == NULL_TREE || maxindex == error_mark_node)
return error_mark_node; return error_mark_node;
if (explicit_default_init_p) if (explicit_value_init_p)
gcc_assert (!init); gcc_assert (!init);
inner_elt_type = strip_array_types (atype); inner_elt_type = strip_array_types (atype);
...@@ -2840,7 +2842,7 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -2840,7 +2842,7 @@ build_vec_init (tree base, tree maxindex, tree init,
We do need to keep going if we're copying an array. */ We do need to keep going if we're copying an array. */
if (from_array if (from_array
|| ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_default_init_p) || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
&& ! (host_integerp (maxindex, 0) && ! (host_integerp (maxindex, 0)
&& (num_initialized_elts && (num_initialized_elts
== tree_low_cst (maxindex, 0) + 1)))) == tree_low_cst (maxindex, 0) + 1))))
...@@ -2889,17 +2891,17 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -2889,17 +2891,17 @@ build_vec_init (tree base, tree maxindex, tree init,
("cannot initialize multi-dimensional array with initializer"); ("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base), elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
0, 0, 0, 0,
/*explicit_default_init_p=*/false, explicit_value_init_p,
0, complain); 0, complain);
} }
else if (!TYPE_NEEDS_CONSTRUCTING (type)) else if (explicit_value_init_p)
elt_init = (cp_build_modify_expr elt_init = build2 (INIT_EXPR, type, to,
(to, INIT_EXPR, build_value_init (type));
build_zero_init (type, size_one_node,
/*static_storage_p=*/false),
complain));
else else
{
gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
elt_init = build_aggr_init (to, init, 0, complain); elt_init = build_aggr_init (to, init, 0, complain);
}
current_stmt_tree ()->stmts_are_full_exprs_p = 1; current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (elt_init); finish_expr_stmt (elt_init);
......
...@@ -339,15 +339,17 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs, ...@@ -339,15 +339,17 @@ build_aggr_init_array (tree return_type, tree fn, tree slot, int nargs,
} }
/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its /* 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 target. TYPE is the type to be initialized.
have.
Build an encapsulation of the initialization to perform Build an AGGR_INIT_EXPR to represent the initialization. This function
and return it so that it can be processed by language-independent differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
and language-specific expression expanders. */ 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 tree
build_cplus_new (tree type, tree init) build_aggr_init_expr (tree type, tree init)
{ {
tree fn; tree fn;
tree slot; tree slot;
...@@ -369,8 +371,6 @@ build_cplus_new (tree type, tree init) ...@@ -369,8 +371,6 @@ build_cplus_new (tree type, tree init)
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0))); && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
slot = build_local_temp (type);
/* We split the CALL_EXPR into its function and its arguments here. /* We split the CALL_EXPR into its function and its arguments here.
Then, in expand_expr, we put them back together. The reason for Then, in expand_expr, we put them back together. The reason for
this is that this expression might be a default argument this is that this expression might be a default argument
...@@ -384,6 +384,8 @@ build_cplus_new (tree type, tree init) ...@@ -384,6 +384,8 @@ build_cplus_new (tree type, tree init)
type, don't mess with AGGR_INIT_EXPR. */ type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type)) if (is_ctor || TREE_ADDRESSABLE (type))
{ {
slot = build_local_temp (type);
if (TREE_CODE(init) == CALL_EXPR) if (TREE_CODE(init) == CALL_EXPR)
rval = build_aggr_init_array (void_type_node, fn, slot, rval = build_aggr_init_array (void_type_node, fn, slot,
call_expr_nargs (init), call_expr_nargs (init),
...@@ -398,6 +400,30 @@ build_cplus_new (tree type, tree init) ...@@ -398,6 +400,30 @@ build_cplus_new (tree type, tree init)
else else
rval = init; 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); rval = build_target_expr (slot, rval);
TARGET_EXPR_IMPLICIT_P (rval) = 1; TARGET_EXPR_IMPLICIT_P (rval) = 1;
...@@ -2687,7 +2713,8 @@ stabilize_init (tree init, tree *initp) ...@@ -2687,7 +2713,8 @@ stabilize_init (tree init, tree *initp)
return true; return true;
if (TREE_CODE (t) == INIT_EXPR if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_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); TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
return true; return true;
......
...@@ -6114,7 +6114,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, ...@@ -6114,7 +6114,7 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0; ? 1 + (modifycode != INIT_EXPR): 0;
return build_vec_init (lhs, NULL_TREE, newrhs, return build_vec_init (lhs, NULL_TREE, newrhs,
/*explicit_default_init_p=*/false, /*explicit_value_init_p=*/false,
from_array, complain); from_array, complain);
} }
......
// { dg-do run { xfail *-*-* } } // { dg-do run }
// XFAILed until PR2123 is fixed
// PR 11228: array operator new, with zero-initialization and a variable sized array. // PR 11228: array operator new, with zero-initialization and a variable sized array.
// Regression test for PR // Regression test for PR
// Author: Matt Austern <austern@apple.com> // Author: Matt Austern <austern@apple.com>
......
// 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();
}
...@@ -4,10 +4,10 @@ ...@@ -4,10 +4,10 @@
int main() { int main() {
int i; int i;
void* operator new(unsigned s, int* p); void* operator new(__SIZE_TYPE__ s, int* p);
int* e = new(&i) int; // { dg-error "no matching function" } int* e = new(&i) int; // { dg-error "no matching function" }
int* f = new int; int* f = new int;
return 0; return 0;
} }
// { dg-excess-errors "operator new" } // { dg-error "candidate" "" { target *-*-* } 0 }
...@@ -20,5 +20,5 @@ double foo (void) ...@@ -20,5 +20,5 @@ double foo (void)
return v.a[2]; return v.a[2];
} }
/* { dg-final { scan-tree-dump "Replaced .*iftmp.* != 0B. with .1" "forwprop1" } } */ /* { dg-final { scan-tree-dump "Replaced .* != 0B. with .1" "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */ /* { dg-final { cleanup-tree-dump "forwprop1" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment