aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.cc')
-rw-r--r--gcc/cp/init.cc62
1 files changed, 55 insertions, 7 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 062a493..f19794c 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3010,7 +3010,6 @@ build_new_constexpr_heap_type (tree elt_type, tree cookie_size, tree itype2)
tree atype1 = build_cplus_array_type (sizetype, itype1);
tree atype2 = build_cplus_array_type (elt_type, itype2);
tree rtype = cxx_make_type (RECORD_TYPE);
- TYPE_NAME (rtype) = heap_identifier;
tree fld1 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype1);
tree fld2 = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, atype2);
DECL_FIELD_CONTEXT (fld1) = rtype;
@@ -3019,7 +3018,16 @@ build_new_constexpr_heap_type (tree elt_type, tree cookie_size, tree itype2)
DECL_ARTIFICIAL (fld2) = true;
TYPE_FIELDS (rtype) = fld1;
DECL_CHAIN (fld1) = fld2;
+ TYPE_ARTIFICIAL (rtype) = true;
layout_type (rtype);
+
+ tree decl = build_decl (UNKNOWN_LOCATION, TYPE_DECL, heap_identifier, rtype);
+ TYPE_NAME (rtype) = decl;
+ TYPE_STUB_DECL (rtype) = decl;
+ DECL_CONTEXT (decl) = NULL_TREE;
+ DECL_ARTIFICIAL (decl) = true;
+ layout_decl (decl, 0);
+
return rtype;
}
@@ -3549,9 +3557,19 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
alloc_expr = maybe_wrap_new_for_constexpr (alloc_expr, type,
cookie_size);
+ bool std_placement = std_placement_new_fn_p (alloc_fn);
+
+ /* For std placement new, clobber the object if the constructor won't do it
+ in start_preparsed_function. This is most important for activating an
+ array in a union (c++/121068), but should also help the optimizers. */
+ const bool do_clobber
+ = (std_placement && !*init && flag_lifetime_dse > 1
+ && (!CLASS_TYPE_P (elt_type)
+ || type_has_non_user_provided_default_constructor (elt_type)));
+
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
- if (!cookie_size && !is_initialized && !member_delete_p)
+ if (!cookie_size && !is_initialized && !member_delete_p && !do_clobber)
return build_nop (pointer_type, alloc_expr);
/* Store the result of the allocation call in a variable so that we can
@@ -3585,8 +3603,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
So check for a null exception spec on the op new we just called. */
nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
- check_new
- = flag_check_new || (nothrow && !std_placement_new_fn_p (alloc_fn));
+ check_new = flag_check_new || (nothrow && !std_placement);
if (cookie_size)
{
@@ -3641,6 +3658,29 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
/* Any further uses of alloc_node will want this type, too. */
alloc_node = fold_convert (non_const_pointer_type, alloc_node);
+ tree clobber_expr = NULL_TREE;
+ if (do_clobber)
+ {
+ tree clobber = build_clobber (elt_type, CLOBBER_OBJECT_BEGIN);
+ CONSTRUCTOR_IS_DIRECT_INIT (clobber) = true;
+ if (array_p)
+ {
+ /* Clobber each element rather than the array at once. */
+ tree maxindex = cp_build_binary_op (input_location,
+ MINUS_EXPR, outer_nelts,
+ integer_one_node,
+ complain);
+ clobber_expr = build_vec_init (data_addr, maxindex, clobber,
+ /*valinit*/false, /*from_arr*/0,
+ complain, nullptr);
+ }
+ else
+ {
+ tree targ = cp_build_fold_indirect_ref (data_addr);
+ clobber_expr = cp_build_init_expr (targ, clobber);
+ }
+ }
+
/* 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
@@ -3869,6 +3909,8 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
if (init_expr)
rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_expr, rval);
+ if (clobber_expr)
+ rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), clobber_expr, rval);
if (cookie_expr)
rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval);
@@ -4173,7 +4215,8 @@ build_vec_delete_1 (location_t loc, tree base, tree maxindex, tree type,
"possible problem detected in invocation of "
"operator %<delete []%>"))
{
- cxx_incomplete_type_diagnostic (base, type, DK_WARNING);
+ cxx_incomplete_type_diagnostic (base, type,
+ diagnostics::kind::warning);
inform (loc, "neither the destructor nor the "
"class-specific operator %<delete []%> will be called, "
"even if they are declared when the class is defined");
@@ -4708,6 +4751,9 @@ build_vec_init (tree base, tree maxindex, tree init,
the partially constructed array if an exception is thrown.
But don't do this if we're assigning. */
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+ /* And don't clean up from clobbers, the actual initialization will
+ follow as a separate build_vec_init. */
+ && !(init && TREE_CLOBBER_P (init))
&& from_array != 2)
{
tree e;
@@ -4747,7 +4793,8 @@ build_vec_init (tree base, tree maxindex, tree init,
itself. But that breaks when gimplify_target_expr adds a clobber
cleanup that runs before the build_vec_init cleanup. */
if (cleanup_flags)
- vec_safe_push (*cleanup_flags, build_tree_list (iterator, maxindex));
+ vec_safe_push (*cleanup_flags,
+ build_tree_list (rval, build_zero_cst (ptype)));
}
/* Should we try to create a constant initializer? */
@@ -5277,7 +5324,8 @@ build_delete (location_t loc, tree otype, tree addr,
"possible problem detected in invocation of "
"%<operator delete%>"))
{
- cxx_incomplete_type_diagnostic (addr, type, DK_WARNING);
+ cxx_incomplete_type_diagnostic (addr, type,
+ diagnostics::kind::warning);
inform (loc,
"neither the destructor nor the class-specific "
"%<operator delete%> will be called, even if "