aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-01-15 14:10:09 -0500
committerJason Merrill <jason@gcc.gnu.org>2014-01-15 14:10:09 -0500
commit4185202700f518a5dd483cf5f45b9b438c52108c (patch)
tree959783072fc5872bc6501b82629d354e383f17ec /gcc/cp
parenta6a2d67b0adf891b823b2b492a9d1cc98e09835a (diff)
downloadgcc-4185202700f518a5dd483cf5f45b9b438c52108c.zip
gcc-4185202700f518a5dd483cf5f45b9b438c52108c.tar.gz
gcc-4185202700f518a5dd483cf5f45b9b438c52108c.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/semantics.c8
-rw-r--r--gcc/cp/typeck2.c147
3 files changed, 98 insertions, 67 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9213de7..c15c8fd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9f87887..eb04266 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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);
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index d9c3647..25edbac 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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);
}