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> 2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com>
PR c++/59631 PR c++/59631
......
...@@ -8961,19 +8961,13 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init, ...@@ -8961,19 +8961,13 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
else else
{ {
/* Copying an element. */ /* Copying an element. */
vec<tree, va_gc> *argvec;
gcc_assert (same_type_ignoring_top_level_qualifiers_p gcc_assert (same_type_ignoring_top_level_qualifiers_p
(atype, TREE_TYPE (init))); (atype, TREE_TYPE (init)));
eltinit = cp_build_array_ref (input_location, init, idx, eltinit = cp_build_array_ref (input_location, init, idx,
tf_warning_or_error); tf_warning_or_error);
if (!real_lvalue_p (init)) if (!real_lvalue_p (init))
eltinit = move (eltinit); eltinit = move (eltinit);
argvec = make_tree_vector (); eltinit = force_rvalue (eltinit, tf_warning_or_error);
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 = cxx_eval_constant_expression eltinit = cxx_eval_constant_expression
(call, eltinit, allow_non_constant, addr, non_constant_p, overflow_p); (call, eltinit, allow_non_constant, addr, non_constant_p, overflow_p);
} }
......
...@@ -631,6 +631,21 @@ split_nonconstant_init_1 (tree dest, tree init) ...@@ -631,6 +631,21 @@ split_nonconstant_init_1 (tree dest, tree init)
CONSTRUCTOR_ELTS (init)->ordered_remove (idx); CONSTRUCTOR_ELTS (init)->ordered_remove (idx);
--idx; --idx;
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
{
if (array_type_p) if (array_type_p)
sub = build4 (ARRAY_REF, inner_type, dest, field_index, sub = build4 (ARRAY_REF, inner_type, dest, field_index,
NULL_TREE, NULL_TREE); NULL_TREE, NULL_TREE);
...@@ -650,6 +665,7 @@ split_nonconstant_init_1 (tree dest, tree init) ...@@ -650,6 +665,7 @@ split_nonconstant_init_1 (tree dest, tree init)
if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type)) if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
finish_eh_cleanup (code); finish_eh_cleanup (code);
} }
}
num_split_elts++; num_split_elts++;
} }
...@@ -1101,6 +1117,22 @@ picflag_from_initializer (tree init) ...@@ -1101,6 +1117,22 @@ picflag_from_initializer (tree init)
return 0; 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 /* Subroutine of process_init_constructor, which will process an initializer
INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*) INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*)
which describe the initializers. */ which describe the initializers. */
...@@ -1158,8 +1190,7 @@ process_init_constructor_array (tree type, tree init, ...@@ -1158,8 +1190,7 @@ process_init_constructor_array (tree type, tree init,
else else
ce->index = size_int (i); ce->index = size_int (i);
gcc_assert (ce->value); gcc_assert (ce->value);
ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, ce->value = massage_init_elt (TREE_TYPE (type), ce->value, complain);
LOOKUP_IMPLICIT, complain);
if (ce->value != error_mark_node) if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p gcc_assert (same_type_ignoring_top_level_qualifiers_p
...@@ -1168,10 +1199,10 @@ process_init_constructor_array (tree type, tree init, ...@@ -1168,10 +1199,10 @@ process_init_constructor_array (tree type, tree init,
flags |= picflag_from_initializer (ce->value); flags |= picflag_from_initializer (ce->value);
} }
/* No more initializers. If the array is unbounded, we are done. Otherwise, /* No more initializers. If the array is unbounded, or we've initialized
we must add initializers ourselves. */ all the elements, we are done. Otherwise, we must add initializers
if (!unbounded) ourselves. */
for (; i < len; ++i) if (!unbounded && i < len)
{ {
tree next; tree next;
...@@ -1181,7 +1212,11 @@ process_init_constructor_array (tree type, tree init, ...@@ -1181,7 +1212,11 @@ process_init_constructor_array (tree type, tree init,
we can't rely on the back end to do it for us, so make the we can't rely on the back end to do it for us, so make the
initialization explicit by list-initializing from {}. */ initialization explicit by list-initializing from {}. */
next = build_constructor (init_list_type_node, NULL); next = build_constructor (init_list_type_node, NULL);
next = digest_init (TREE_TYPE (type), next, complain); 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))) else if (!zero_init_p (TREE_TYPE (type)))
next = build_zero_init (TREE_TYPE (type), next = build_zero_init (TREE_TYPE (type),
...@@ -1190,10 +1225,15 @@ process_init_constructor_array (tree type, tree init, ...@@ -1190,10 +1225,15 @@ process_init_constructor_array (tree type, tree init,
else else
/* The default zero-initialization is fine for us; don't /* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */ add anything to the CONSTRUCTOR. */
break; next = NULL_TREE;
if (next)
{
flags |= picflag_from_initializer (next); flags |= picflag_from_initializer (next);
CONSTRUCTOR_APPEND_ELT (v, size_int (i), next); tree index = build2 (RANGE_EXPR, sizetype, size_int (i),
size_int (len - 1));
CONSTRUCTOR_APPEND_ELT (v, index, next);
}
} }
CONSTRUCTOR_ELTS (init) = v; CONSTRUCTOR_ELTS (init) = v;
...@@ -1263,8 +1303,7 @@ process_init_constructor_record (tree type, tree init, ...@@ -1263,8 +1303,7 @@ process_init_constructor_record (tree type, tree init,
} }
gcc_assert (ce->value); gcc_assert (ce->value);
next = digest_init_r (type, ce->value, true, next = massage_init_elt (type, ce->value, complain);
LOOKUP_IMPLICIT, complain);
++idx; ++idx;
} }
else if (type_build_ctor_call (TREE_TYPE (field))) else if (type_build_ctor_call (TREE_TYPE (field)))
...@@ -1274,18 +1313,7 @@ process_init_constructor_record (tree type, tree init, ...@@ -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 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. */ a class, just build one up; if it's an array, recurse. */
next = build_constructor (init_list_type_node, NULL); next = build_constructor (init_list_type_node, NULL);
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field))) next = massage_init_elt (TREE_TYPE (field), next, complain);
{
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);
/* Warn when some struct elements are implicitly initialized. */ /* Warn when some struct elements are implicitly initialized. */
warning (OPT_Wmissing_field_initializers, warning (OPT_Wmissing_field_initializers,
...@@ -1422,8 +1450,7 @@ process_init_constructor_union (tree type, tree init, ...@@ -1422,8 +1450,7 @@ process_init_constructor_union (tree type, tree init,
} }
if (ce->value && ce->value != error_mark_node) if (ce->value && ce->value != error_mark_node)
ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, ce->value = massage_init_elt (TREE_TYPE (ce->index), ce->value, complain);
true, LOOKUP_IMPLICIT, complain);
return picflag_from_initializer (ce->value); 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