diff options
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r-- | gcc/cp/init.c | 137 |
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); |