Commit c0014b07 by Jason Merrill Committed by Jason Merrill

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
parent ced2fb08
2014-08-06 Jason Merrill <jason@redhat.com> 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 PR c++/60417
* init.c (build_vec_init): Reorganize earlier change a bit. * init.c (build_vec_init): Reorganize earlier change a bit.
......
...@@ -419,12 +419,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ...@@ -419,12 +419,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
over TYPE_FIELDs will result in correct initialization of over TYPE_FIELDs will result in correct initialization of
all of the subobjects. */ all of the subobjects. */
value = build_value_init (ftype, complain); value = build_value_init (ftype, complain);
value = maybe_constant_init (value);
if (value == error_mark_node) if (value == error_mark_node)
return 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. */ /* Build a constructor to contain the zero- initializations. */
...@@ -462,20 +468,18 @@ build_value_init_noctor (tree type, tsubst_flags_t complain) ...@@ -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.index = build2 (RANGE_EXPR, sizetype, size_zero_node, max_index);
ce.value = build_value_init (TREE_TYPE (type), complain); ce.value = build_value_init (TREE_TYPE (type), complain);
if (ce.value) ce.value = maybe_constant_init (ce.value);
{ if (ce.value == error_mark_node)
if (ce.value == error_mark_node) return error_mark_node;
return error_mark_node;
vec_alloc (v, 1); vec_alloc (v, 1);
v->quick_push (ce); v->quick_push (ce);
/* We shouldn't have gotten here for anything that would need /* We shouldn't have gotten here for anything that would need
non-trivial initialization, and gimplify_init_ctor_preeval non-trivial initialization, and gimplify_init_ctor_preeval
would need to be fixed to allow it. */ would need to be fixed to allow it. */
gcc_assert (TREE_CODE (ce.value) != TARGET_EXPR gcc_assert (TREE_CODE (ce.value) != TARGET_EXPR
&& TREE_CODE (ce.value) != AGGR_INIT_EXPR); && TREE_CODE (ce.value) != AGGR_INIT_EXPR);
}
} }
/* Build a constructor to contain the initializations. */ /* Build a constructor to contain the initializations. */
...@@ -3412,7 +3416,6 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3412,7 +3416,6 @@ build_vec_init (tree base, tree maxindex, tree init,
tree try_block = NULL_TREE; tree try_block = NULL_TREE;
int num_initialized_elts = 0; int num_initialized_elts = 0;
bool is_global; bool is_global;
tree const_init = NULL_TREE;
tree obase = base; tree obase = base;
bool xvalue = false; bool xvalue = false;
bool errors = false; bool errors = false;
...@@ -3545,6 +3548,19 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3545,6 +3548,19 @@ build_vec_init (tree base, tree maxindex, tree init,
try_block = begin_try_block (); 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; bool empty_list = false;
if (init && BRACE_ENCLOSED_INITIALIZER_P (init) if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CONSTRUCTOR_NELTS (init) == 0) && CONSTRUCTOR_NELTS (init) == 0)
...@@ -3559,21 +3575,9 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3559,21 +3575,9 @@ build_vec_init (tree base, tree maxindex, tree init,
brace-enclosed initializers. */ brace-enclosed initializers. */
unsigned HOST_WIDE_INT idx; unsigned HOST_WIDE_INT idx;
tree field, elt; 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 /* If the constructor already has the array type, it's been through
digest_init, so we shouldn't try to do anything more. */ digest_init, so we shouldn't try to do anything more. */
bool digested = same_type_p (atype, TREE_TYPE (init)); 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; from_array = 0;
if (length_check) if (length_check)
...@@ -3589,9 +3593,7 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3589,9 +3593,7 @@ build_vec_init (tree base, tree maxindex, tree init,
} }
if (try_const) if (try_const)
vec_alloc (new_vec, CONSTRUCTOR_NELTS (init)); vec_alloc (const_vec, CONSTRUCTOR_NELTS (init));
else
new_vec = NULL;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt) FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, field, elt)
{ {
...@@ -3612,21 +3614,14 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3612,21 +3614,14 @@ build_vec_init (tree base, tree maxindex, tree init,
errors = true; errors = true;
if (try_const) if (try_const)
{ {
tree e = one_init; tree e = maybe_constant_init (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);
if (reduced_constant_expression_p (e)) if (reduced_constant_expression_p (e))
{ {
CONSTRUCTOR_APPEND_ELT (new_vec, field, e); CONSTRUCTOR_APPEND_ELT (const_vec, field, e);
if (do_static_init) if (do_static_init)
one_init = NULL_TREE; one_init = NULL_TREE;
else else
one_init = build2 (INIT_EXPR, type, baseref, e); one_init = build2 (INIT_EXPR, type, baseref, e);
saw_const = true;
} }
else else
{ {
...@@ -3635,7 +3630,7 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3635,7 +3630,7 @@ build_vec_init (tree base, tree maxindex, tree init,
tree value = build_zero_init (TREE_TYPE (e), NULL_TREE, tree value = build_zero_init (TREE_TYPE (e), NULL_TREE,
true); true);
if (value) if (value)
CONSTRUCTOR_APPEND_ELT (new_vec, field, value); CONSTRUCTOR_APPEND_ELT (const_vec, field, value);
} }
saw_non_const = true; saw_non_const = true;
} }
...@@ -3659,16 +3654,6 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3659,16 +3654,6 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_expr_stmt (one_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{}. */ /* Any elements without explicit initializers get T{}. */
empty_list = true; empty_list = true;
} }
...@@ -3793,8 +3778,38 @@ build_vec_init (tree base, tree maxindex, tree init, ...@@ -3793,8 +3778,38 @@ build_vec_init (tree base, tree maxindex, tree init,
if (elt_init == error_mark_node) if (elt_init == error_mark_node)
errors = true; 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; 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; current_stmt_tree ()->stmts_are_full_exprs_p = 0;
finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 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, ...@@ -3844,8 +3859,19 @@ build_vec_init (tree base, tree maxindex, tree init,
if (errors) if (errors)
return error_mark_node; 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. */ /* Now make the result have the correct type. */
if (TREE_CODE (atype) == ARRAY_TYPE) if (TREE_CODE (atype) == ARRAY_TYPE)
......
...@@ -9976,6 +9976,11 @@ maybe_constant_value (tree t) ...@@ -9976,6 +9976,11 @@ maybe_constant_value (tree t)
tree tree
maybe_constant_init (tree t) 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); t = maybe_constant_value (t);
if (TREE_CODE (t) == TARGET_EXPR) if (TREE_CODE (t) == TARGET_EXPR)
{ {
......
// { 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();
}
// { 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();
}
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