Commit 41852027 by Jason Merrill Committed by Jason Merrill

re PR c++/59659 (large zero-initialized std::array compile time excessive)

	PR c++/59659
	* typeck2.c (massage_init_elt): New.
	(process_init_constructor_record)
	(process_init_constructor_union): Use it.
	(process_init_constructor_array): Use it.  Use RANGE_EXPR.
	(split_nonconstant_init_1): Handle it.
	* semantics.c (cxx_eval_vec_init_1): Use force_rvalue.

From-SVN: r206639
parent a6a2d67b
2014-01-14 Jason Merrill <jason@redhat.com>
PR c++/59659
* typeck2.c (massage_init_elt): New.
(process_init_constructor_record)
(process_init_constructor_union): Use it.
(process_init_constructor_array): Use it. Use RANGE_EXPR.
(split_nonconstant_init_1): Handle it.
* semantics.c (cxx_eval_vec_init_1): Use force_rvalue.
2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com>
PR c++/59631
......
......@@ -8961,19 +8961,13 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
else
{
/* Copying an element. */
vec<tree, va_gc> *argvec;
gcc_assert (same_type_ignoring_top_level_qualifiers_p
(atype, TREE_TYPE (init)));
eltinit = cp_build_array_ref (input_location, init, idx,
tf_warning_or_error);
if (!real_lvalue_p (init))
eltinit = move (eltinit);
argvec = make_tree_vector ();
argvec->quick_push (eltinit);
eltinit = (build_special_member_call
(NULL_TREE, complete_ctor_identifier, &argvec,
elttype, LOOKUP_NORMAL, tf_warning_or_error));
release_tree_vector (argvec);
eltinit = force_rvalue (eltinit, tf_warning_or_error);
eltinit = cxx_eval_constant_expression
(call, eltinit, allow_non_constant, addr, non_constant_p, overflow_p);
}
......
......@@ -631,24 +631,40 @@ split_nonconstant_init_1 (tree dest, tree init)
CONSTRUCTOR_ELTS (init)->ordered_remove (idx);
--idx;
if (array_type_p)
sub = build4 (ARRAY_REF, inner_type, dest, field_index,
NULL_TREE, NULL_TREE);
if (TREE_CODE (field_index) == RANGE_EXPR)
{
/* Use build_vec_init to initialize a range. */
tree low = TREE_OPERAND (field_index, 0);
tree hi = TREE_OPERAND (field_index, 1);
sub = build4 (ARRAY_REF, inner_type, dest, low,
NULL_TREE, NULL_TREE);
sub = cp_build_addr_expr (sub, tf_warning_or_error);
tree max = size_binop (MINUS_EXPR, hi, low);
code = build_vec_init (sub, max, value, false, 0,
tf_warning_or_error);
add_stmt (code);
}
else
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (input_location, EXPR_STMT, code);
code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
if (type_build_dtor_call (inner_type))
{
code = (build_special_member_call
(sub, complete_dtor_identifier, NULL, inner_type,
LOOKUP_NORMAL, tf_warning_or_error));
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
finish_eh_cleanup (code);
if (array_type_p)
sub = build4 (ARRAY_REF, inner_type, dest, field_index,
NULL_TREE, NULL_TREE);
else
sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
NULL_TREE);
code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (input_location, EXPR_STMT, code);
code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
if (type_build_dtor_call (inner_type))
{
code = (build_special_member_call
(sub, complete_dtor_identifier, NULL, inner_type,
LOOKUP_NORMAL, tf_warning_or_error));
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
finish_eh_cleanup (code);
}
}
num_split_elts++;
......@@ -1101,6 +1117,22 @@ picflag_from_initializer (tree init)
return 0;
}
/* Adjust INIT for going into a CONSTRUCTOR. */
static tree
massage_init_elt (tree type, tree init, tsubst_flags_t complain)
{
init = digest_init_r (type, init, true, LOOKUP_IMPLICIT, complain);
/* Strip a simple TARGET_EXPR when we know this is an initializer. */
if (TREE_CODE (init) == TARGET_EXPR
&& !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (init))))
init = TARGET_EXPR_INITIAL (init);
/* When we defer constant folding within a statement, we may want to
defer this folding as well. */
init = maybe_constant_init (init);
return init;
}
/* Subroutine of process_init_constructor, which will process an initializer
INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*)
which describe the initializers. */
......@@ -1158,8 +1190,7 @@ process_init_constructor_array (tree type, tree init,
else
ce->index = size_int (i);
gcc_assert (ce->value);
ce->value = digest_init_r (TREE_TYPE (type), ce->value, true,
LOOKUP_IMPLICIT, complain);
ce->value = massage_init_elt (TREE_TYPE (type), ce->value, complain);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
......@@ -1168,33 +1199,42 @@ process_init_constructor_array (tree type, tree init,
flags |= picflag_from_initializer (ce->value);
}
/* No more initializers. If the array is unbounded, we are done. Otherwise,
we must add initializers ourselves. */
if (!unbounded)
for (; i < len; ++i)
{
tree next;
if (type_build_ctor_call (TREE_TYPE (type)))
{
/* If this type needs constructors run for default-initialization,
we can't rely on the back end to do it for us, so make the
initialization explicit by list-initializing from {}. */
next = build_constructor (init_list_type_node, NULL);
next = digest_init (TREE_TYPE (type), next, complain);
}
else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type),
/*nelts=*/NULL_TREE,
/*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
break;
/* No more initializers. If the array is unbounded, or we've initialized
all the elements, we are done. Otherwise, we must add initializers
ourselves. */
if (!unbounded && i < len)
{
tree next;
flags |= picflag_from_initializer (next);
CONSTRUCTOR_APPEND_ELT (v, size_int (i), next);
}
if (type_build_ctor_call (TREE_TYPE (type)))
{
/* If this type needs constructors run for default-initialization,
we can't rely on the back end to do it for us, so make the
initialization explicit by list-initializing from {}. */
next = build_constructor (init_list_type_node, NULL);
next = massage_init_elt (TREE_TYPE (type), next, complain);
if (initializer_zerop (next))
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
next = NULL_TREE;
}
else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type),
/*nelts=*/NULL_TREE,
/*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
next = NULL_TREE;
if (next)
{
flags |= picflag_from_initializer (next);
tree index = build2 (RANGE_EXPR, sizetype, size_int (i),
size_int (len - 1));
CONSTRUCTOR_APPEND_ELT (v, index, next);
}
}
CONSTRUCTOR_ELTS (init) = v;
return flags;
......@@ -1263,8 +1303,7 @@ process_init_constructor_record (tree type, tree init,
}
gcc_assert (ce->value);
next = digest_init_r (type, ce->value, true,
LOOKUP_IMPLICIT, complain);
next = massage_init_elt (type, ce->value, complain);
++idx;
}
else if (type_build_ctor_call (TREE_TYPE (field)))
......@@ -1274,18 +1313,7 @@ process_init_constructor_record (tree type, tree init,
for us, so build up TARGET_EXPRs. If the type in question is
a class, just build one up; if it's an array, recurse. */
next = build_constructor (init_list_type_node, NULL);
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field)))
{
next = finish_compound_literal (TREE_TYPE (field), next,
complain);
/* direct-initialize the target. No temporary is going
to be involved. */
if (TREE_CODE (next) == TARGET_EXPR)
TARGET_EXPR_DIRECT_INIT_P (next) = true;
}
next = digest_init_r (TREE_TYPE (field), next, true,
LOOKUP_IMPLICIT, complain);
next = massage_init_elt (TREE_TYPE (field), next, complain);
/* Warn when some struct elements are implicitly initialized. */
warning (OPT_Wmissing_field_initializers,
......@@ -1422,8 +1450,7 @@ process_init_constructor_union (tree type, tree init,
}
if (ce->value && ce->value != error_mark_node)
ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value,
true, LOOKUP_IMPLICIT, complain);
ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, complain);
return picflag_from_initializer (ce->value);
}
......
// PR c++/59659
// { dg-options "-fdump-tree-gimple -std=c++11" }
// { dg-final { scan-tree-dump-times "i = 0" 0 "gimple" } }
// { dg-final { cleanup-tree-dump "gimple" } }
struct S { S () = default; S (int i); int i; };
struct A { S s[100]; };
void
foo ()
{
A a = {{}};
}
// PR c++/59659
// { dg-options "-fdump-tree-gimple" }
// { dg-final { scan-tree-dump-times "S::S" 1 "gimple" } }
// { dg-final { cleanup-tree-dump "gimple" } }
struct S { S (); S (int i); int i; };
struct A { S s[100]; };
void
foo ()
{
A a = {{}};
}
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