diff options
author | Jason Merrill <jason@redhat.com> | 2014-08-06 21:44:40 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-08-06 21:44:40 -0400 |
commit | c0014b079fe34362888727502986ce7af50462b6 (patch) | |
tree | 7a2eca9735cdf863cc4b5e88bd27f5763bf4c02f | |
parent | ced2fb085c43bef21e863989129c54279b7c8e48 (diff) | |
download | gcc-c0014b079fe34362888727502986ce7af50462b6.zip gcc-c0014b079fe34362888727502986ce7af50462b6.tar.gz gcc-c0014b079fe34362888727502986ce7af50462b6.tar.bz2 |
init.c (build_vec_init): Fix constant initialization of trailing elements.
* init.c (build_vec_init): Fix constant initialization of
trailing elements.
(build_value_init_noctor): Call maybe_constant_init.
* semantics.c (maybe_constant_init): See through EXPR_STMT and
conversion to void.
From-SVN: r213690
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/init.c | 132 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-array8.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-array9.C | 22 |
5 files changed, 134 insertions, 53 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a373ccf..3f159a7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2014-08-06 Jason Merrill <jason@redhat.com> + * init.c (build_vec_init): Fix constant initialization of + trailing elements. + (build_value_init_noctor): Call maybe_constant_init. + * semantics.c (maybe_constant_init): See through EXPR_STMT and + conversion to void. + PR c++/60417 * init.c (build_vec_init): Reorganize earlier change a bit. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 777e0a9..f0ca9b9 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -419,12 +419,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) over TYPE_FIELDs will result in correct initialization of all of the subobjects. */ value = build_value_init (ftype, complain); + value = maybe_constant_init (value); if (value == error_mark_node) return error_mark_node; - if (value) - CONSTRUCTOR_APPEND_ELT(v, field, value); + CONSTRUCTOR_APPEND_ELT(v, field, value); + + /* We shouldn't have gotten here for anything that would need + non-trivial initialization, and gimplify_init_ctor_preeval + would need to be fixed to allow it. */ + gcc_assert (TREE_CODE (value) != TARGET_EXPR + && TREE_CODE (value) != AGGR_INIT_EXPR); } /* Build a constructor to contain the zero- initializations. */ @@ -462,20 +468,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ce.index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index); ce.value = build_value_init (TREE_TYPE (type), complain); - if (ce.value) - { - if (ce.value == error_mark_node) - return error_mark_node; + ce.value = maybe_constant_init (ce.value); + if (ce.value == error_mark_node) + return error_mark_node; - vec_alloc (v, 1); - v->quick_push (ce); + vec_alloc (v, 1); + v->quick_push (ce); - /* We shouldn't have gotten here for anything that would need - non-trivial initialization, and gimplify_init_ctor_preeval - would need to be fixed to allow it. */ - gcc_assert (TREE_CODE (ce.value) != TARGET_EXPR - && TREE_CODE (ce.value) != AGGR_INIT_EXPR); - } + /* We shouldn't have gotten here for anything that would need + non-trivial initialization, and gimplify_init_ctor_preeval + would need to be fixed to allow it. */ + gcc_assert (TREE_CODE (ce.value) != TARGET_EXPR + && TREE_CODE (ce.value) != AGGR_INIT_EXPR); } /* Build a constructor to contain the initializations. */ @@ -3412,7 +3416,6 @@ build_vec_init (tree base, tree maxindex, tree init, tree try_block = NULL_TREE; int num_initialized_elts = 0; bool is_global; - tree const_init = NULL_TREE; tree obase = base; bool xvalue = false; bool errors = false; @@ -3545,6 +3548,19 @@ build_vec_init (tree base, tree maxindex, tree init, try_block = begin_try_block (); } + /* Should we try to create a constant initializer? */ + bool try_const = (TREE_CODE (atype) == ARRAY_TYPE + && TREE_CONSTANT (maxindex) + && init && TREE_CODE (init) == CONSTRUCTOR + && (literal_type_p (inner_elt_type) + || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type))); + vec<constructor_elt, va_gc> *const_vec = NULL; + bool saw_non_const = false; + /* If we're initializing a static array, we want to do static + initialization of any elements with constant initializers even if + some are non-constant. */ + bool do_static_init = (DECL_P (obase) && TREE_STATIC (obase)); + bool empty_list = false; if (init && BRACE_ENCLOSED_INITIALIZER_P (init) && CONSTRUCTOR_NELTS (init) == 0) @@ -3559,21 +3575,9 @@ build_vec_init (tree base, tree maxindex, tree init, brace-enclosed initializers. */ unsigned HOST_WIDE_INT idx; tree field, elt; - /* Should we try to create a constant initializer? */ - bool try_const = (TREE_CODE (atype) == ARRAY_TYPE - && TREE_CONSTANT (maxindex) - && (literal_type_p (inner_elt_type) - || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type))); /* If the constructor already has the array type, it's been through digest_init, so we shouldn't try to do anything more. */ bool digested = same_type_p (atype, TREE_TYPE (init)); - bool saw_non_const = false; - bool saw_const = false; - /* If we're initializing a static array, we want to do static - initialization of any elements with constant initializers even if - some are non-constant. */ - bool do_static_init = (DECL_P (obase) && TREE_STATIC (obase)); - vec<constructor_elt, va_gc> *new_vec; from_array = 0; if (length_check) @@ -3589,9 +3593,7 @@ build_vec_init (tree base, tree maxindex, tree init, } if (try_const) - vec_alloc (new_vec, CONSTRUCTOR_NELTS (init)); - else - new_vec = NULL; + vec_alloc (const_vec, CONSTRUCTOR_NELTS (init)); FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt) { @@ -3612,21 +3614,14 @@ build_vec_init (tree base, tree maxindex, tree init, errors = true; if (try_const) { - tree e = one_init; - if (TREE_CODE (e) == EXPR_STMT) - e = TREE_OPERAND (e, 0); - if (TREE_CODE (e) == CONVERT_EXPR - && VOID_TYPE_P (TREE_TYPE (e))) - e = TREE_OPERAND (e, 0); - e = maybe_constant_init (e); + tree e = maybe_constant_init (one_init); if (reduced_constant_expression_p (e)) { - CONSTRUCTOR_APPEND_ELT (new_vec, field, e); + CONSTRUCTOR_APPEND_ELT (const_vec, field, e); if (do_static_init) one_init = NULL_TREE; else one_init = build2 (INIT_EXPR, type, baseref, e); - saw_const = true; } else { @@ -3635,7 +3630,7 @@ build_vec_init (tree base, tree maxindex, tree init, tree value = build_zero_init (TREE_TYPE (e), NULL_TREE, true); if (value) - CONSTRUCTOR_APPEND_ELT (new_vec, field, value); + CONSTRUCTOR_APPEND_ELT (const_vec, field, value); } saw_non_const = true; } @@ -3659,16 +3654,6 @@ build_vec_init (tree base, tree maxindex, tree init, finish_expr_stmt (one_init); } - if (try_const) - { - if (!saw_non_const) - const_init = build_constructor (atype, new_vec); - else if (do_static_init && saw_const) - DECL_INITIAL (obase) = build_constructor (atype, new_vec); - else - vec_free (new_vec); - } - /* Any elements without explicit initializers get T{}. */ empty_list = true; } @@ -3793,8 +3778,38 @@ build_vec_init (tree base, tree maxindex, tree init, if (elt_init == error_mark_node) errors = true; + if (try_const) + { + tree e = maybe_constant_init (elt_init); + if (reduced_constant_expression_p (e)) + { + if (initializer_zerop (e)) + /* Don't fill the CONSTRUCTOR with zeros. */ + e = NULL_TREE; + if (do_static_init) + elt_init = NULL_TREE; + } + else + { + saw_non_const = true; + if (do_static_init) + e = build_zero_init (TREE_TYPE (e), NULL_TREE, true); + } + + if (e) + { + int max = tree_to_shwi (maxindex)+1; + for (; num_initialized_elts < max; ++num_initialized_elts) + { + tree field = size_int (num_initialized_elts); + CONSTRUCTOR_APPEND_ELT (const_vec, field, e); + } + } + } + current_stmt_tree ()->stmts_are_full_exprs_p = 1; - finish_expr_stmt (elt_init); + if (elt_init) + finish_expr_stmt (elt_init); current_stmt_tree ()->stmts_are_full_exprs_p = 0; finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0, @@ -3844,8 +3859,19 @@ build_vec_init (tree base, tree maxindex, tree init, if (errors) return error_mark_node; - if (const_init) - return build2 (INIT_EXPR, atype, obase, const_init); + + if (try_const) + { + if (!saw_non_const) + { + tree const_init = build_constructor (atype, const_vec); + return build2 (INIT_EXPR, atype, obase, const_init); + } + else if (do_static_init && !vec_safe_is_empty (const_vec)) + DECL_INITIAL (obase) = build_constructor (atype, const_vec); + else + vec_free (const_vec); + } /* Now make the result have the correct type. */ if (TREE_CODE (atype) == ARRAY_TYPE) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 859550b..536ea5c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -9976,6 +9976,11 @@ maybe_constant_value (tree t) tree maybe_constant_init (tree t) { + if (TREE_CODE (t) == EXPR_STMT) + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == CONVERT_EXPR + && VOID_TYPE_P (TREE_TYPE (t))) + t = TREE_OPERAND (t, 0); t = maybe_constant_value (t); if (TREE_CODE (t) == TARGET_EXPR) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array8.C new file mode 100644 index 0000000..f4aae4f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array8.C @@ -0,0 +1,22 @@ +// { dg-do run { target c++11 } } + +struct A { int i,j; }; + +struct X { + A a = {1,1}; +}; + +constexpr X table[2][2] = {{ {} }}; + +#define SA(X) static_assert(X,#X) +SA(table[1][1].a.i == 1); + +extern "C" void abort(); + +const int *p = &table[1][1].a.j; + +int main() +{ + if (*p != 1) + abort(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array9.C new file mode 100644 index 0000000..20ec255 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array9.C @@ -0,0 +1,22 @@ +// { dg-do run { target c++11 } } + +struct A { int i,j; }; + +struct X { + A a = {0,0}; +}; + +constexpr X table[2][2] = {{ {} }}; + +#define SA(X) static_assert(X,#X) +SA(table[1][1].a.i == 0); + +extern "C" void abort(); + +const int *p = &table[1][1].a.j; + +int main() +{ + if (*p != 0) + abort(); +} |