aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-08-06 21:44:40 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-08-06 21:44:40 -0400
commitc0014b079fe34362888727502986ce7af50462b6 (patch)
tree7a2eca9735cdf863cc4b5e88bd27f5763bf4c02f
parentced2fb085c43bef21e863989129c54279b7c8e48 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/init.c132
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array8.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-array9.C22
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();
+}