aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@redhat.com>2004-05-13 06:41:07 +0000
committerDiego Novillo <dnovillo@redhat.com>2004-05-13 06:41:07 +0000
commit60ac8927839c69492fc46bf03880f34820cc0570 (patch)
treea2568888a519c077427b133de9ece5879a8484a5 /gcc/cp/init.c
parentfb7359384dbf6f77df81d6bc73b0b5943c52e6d6 (diff)
Merge tree-ssa-20020619-branch into mainline.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@81764 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c137
1 files changed, 73 insertions, 64 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6811aaab58e..8cf0019cfab 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -248,7 +248,10 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
/* In all cases, the initializer is a constant. */
if (init)
- TREE_CONSTANT (init) = 1;
+ {
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ }
return init;
}
@@ -728,12 +731,9 @@ build_vtbl_address (tree binfo)
TREE_USED (vtbl) = 1;
/* Now compute the address to use when initializing the vptr. */
- vtbl = BINFO_VTABLE (binfo_for);
+ vtbl = unshare_expr (BINFO_VTABLE (binfo_for));
if (TREE_CODE (vtbl) == VAR_DECL)
- {
- vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
- TREE_CONSTANT (vtbl) = 1;
- }
+ vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
return vtbl;
}
@@ -767,7 +767,8 @@ expand_virtual_init (tree binfo, tree decl)
TREE_TYPE (vtt_parm),
vtt_parm,
vtt_index);
- vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
+ vtbl2 = build_indirect_ref (vtbl2, NULL);
+ vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
/* The actual initializer is the VTT value only in the subobject
constructor. In maybe_clone_body we'll substitute NULL for
@@ -1143,9 +1144,13 @@ build_init (tree decl, tree init, int flags)
{
tree expr;
- if (IS_AGGR_TYPE (TREE_TYPE (decl))
- || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, flags);
+ else if (CLASS_TYPE_P (TREE_TYPE (decl)))
+ expr = build_special_member_call (decl, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, init),
+ TYPE_BINFO (TREE_TYPE (decl)),
+ LOOKUP_NORMAL|flags);
else
expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
@@ -1825,7 +1830,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
- TREE_NO_UNUSED_WARNING (rval) = 1;
+ TREE_NO_WARNING (rval) = 1;
return rval;
}
@@ -1908,7 +1913,7 @@ static tree
build_new_1 (tree exp)
{
tree placement, init;
- tree true_type, size, rval, t;
+ tree true_type, size, rval;
/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
@@ -1949,6 +1954,7 @@ build_new_1 (tree exp)
address of the first array element. This node is a VAR_DECL, and
is therefore reusable. */
tree data_addr;
+ tree init_preeval_expr = NULL_TREE;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2009,7 +2015,9 @@ build_new_1 (tree exp)
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),
&alloc_decl))
{
@@ -2115,18 +2123,8 @@ build_new_1 (tree exp)
placement delete. */
if (placement_allocation_fn_p)
{
- tree inits = NULL_TREE;
- t = TREE_CHAIN (TREE_OPERAND (alloc_call, 1));
- for (; t; t = TREE_CHAIN (t))
- if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
- {
- tree init;
- TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
- if (inits)
- inits = build (COMPOUND_EXPR, void_type_node, inits, init);
- else
- inits = init;
- }
+ tree inits;
+ stabilize_call (alloc_call, &inits);
if (inits)
alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits,
alloc_expr);
@@ -2169,27 +2167,43 @@ build_new_1 (tree exp)
data_addr = alloc_node;
}
- /* Now initialize the allocated object. */
+ /* Now initialize the allocated object. Note that we preevaluate the
+ initialization expression, apart from the actual constructor call or
+ assignment--we do this because we want to delay the allocation as long
+ as possible in order to minimize the size of the exception region for
+ placement delete. */
if (is_initialized)
{
+ bool stable;
+
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)
+ 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),
- init, /*from_array=*/0);
+ {
+ init_expr
+ = build_vec_init (init_expr,
+ cp_build_binary_op (MINUS_EXPR, outer_nelts,
+ integer_one_node),
+ init, /*from_array=*/0);
+
+ /* An array initialization is stable because the initialization
+ of each element is a full-expression, so the temporaries don't
+ leak out. */
+ stable = true;
+ }
else if (TYPE_NEEDS_CONSTRUCTING (type))
- init_expr = build_special_member_call (init_expr,
- complete_ctor_identifier,
- init, TYPE_BINFO (true_type),
- LOOKUP_NORMAL);
+ {
+ init_expr = build_special_member_call (init_expr,
+ complete_ctor_identifier,
+ init, TYPE_BINFO (true_type),
+ LOOKUP_NORMAL);
+ stable = stabilize_init (init_expr, &init_preeval_expr);
+ }
else
{
/* We are processing something like `new int (10)', which
@@ -2197,15 +2211,13 @@ build_new_1 (tree exp)
if (TREE_CODE (init) == TREE_LIST)
init = build_x_compound_expr_from_list (init, "new initializer");
-
+
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_TYPE (init) == NULL_TREE)
- {
- pedwarn ("ISO C++ forbids aggregate initializer to new");
- init = digest_init (type, init, 0);
- }
+ abort ();
init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
+ stable = stabilize_init (init_expr, &init_preeval_expr);
}
if (init_expr == error_mark_node)
@@ -2232,31 +2244,24 @@ build_new_1 (tree exp)
(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
- if sentry is true. Then we run the constructor, and finally
- clear the sentry.
-
- It would be nice to be able to handle this without the sentry
- variable, perhaps with a TRY_CATCH_EXPR, but this doesn't
- work. We allocate the space first, so if there are any
- temporaries with cleanups in the constructor args we need this
- EH region to extend until end of full-expression to preserve
- nesting.
-
- If the backend had some mechanism so that we could force the
- allocation to be expanded after all the other args to the
- constructor, that would fix the nesting problem and we could
- do away with this complexity. But that would complicate other
- things; in particular, it would make it difficult to bail out
- if the allocation function returns null. Er, no, it wouldn't;
- we just don't run the constructor. The standard says it's
- unspecified whether or not the args are evaluated.
-
- FIXME FIXME FIXME inline invisible refs as refs. That way we
- can preevaluate value parameters. */
-
- if (cleanup)
+ if (!cleanup)
+ /* We're done. */;
+ else if (stable)
+ /* This is much simpler if we were able to preevaluate all of
+ the arguments to the constructor call. */
+ init_expr = build (TRY_CATCH_EXPR, void_type_node,
+ init_expr, cleanup);
+ else
+ /* Ack! First we allocate the memory. Then we set our sentry
+ variable to true, and expand a cleanup that deletes the
+ memory if sentry is true. Then we run the constructor, and
+ finally clear the sentry.
+
+ We need to do this because we allocate the space first, so
+ if there are any temporaries with cleanups in the
+ constructor args and we weren't able to preevaluate them, we
+ need this EH region to extend until end of full-expression
+ to preserve nesting. */
{
tree end, sentry, begin;
@@ -2277,6 +2282,7 @@ build_new_1 (tree exp)
build (COMPOUND_EXPR, void_type_node, init_expr,
end));
}
+
}
}
else
@@ -2309,6 +2315,9 @@ build_new_1 (tree exp)
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
}
+ if (init_preeval_expr)
+ rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
+
/* Convert to the final type. */
rval = build_nop (pointer_type, rval);