PR c++/77945 - constexpr and trivial copy

* constexpr.c (maybe_simplify_trivial_copy): New.
	(cxx_eval_store_expression): Call it.
	* call.c (build_over_call): Use unsigned char for trivial copy.

From-SVN: r241204
This commit is contained in:
Jason Merrill 2016-10-15 17:25:55 -04:00 committed by Jason Merrill
parent f9e9d32f79
commit 68d0192058
4 changed files with 45 additions and 1 deletions

View File

@ -1,3 +1,10 @@
2016-10-15 Jason Merrill <jason@redhat.com>
PR c++/77945
* constexpr.c (maybe_simplify_trivial_copy): New.
(cxx_eval_store_expression): Call it.
* call.c (build_over_call): Use unsigned char for trivial copy.
2016-10-14 Jason Merrill <jason@redhat.com> 2016-10-14 Jason Merrill <jason@redhat.com>
Implement P0017R1, C++17 aggregates with bases. Implement P0017R1, C++17 aggregates with bases.

View File

@ -7909,7 +7909,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
arg2 = TYPE_SIZE_UNIT (as_base); arg2 = TYPE_SIZE_UNIT (as_base);
arg0 = cp_build_addr_expr (to, complain); arg0 = cp_build_addr_expr (to, complain);
array_type = build_array_type (char_type_node, array_type = build_array_type (unsigned_char_type_node,
build_index_type build_index_type
(size_binop (MINUS_EXPR, (size_binop (MINUS_EXPR,
arg2, size_int (1)))); arg2, size_int (1))));

View File

@ -3206,6 +3206,26 @@ var_in_maybe_constexpr_fn (tree t)
return var_in_constexpr_fn (t); return var_in_constexpr_fn (t);
} }
/* We're assigning INIT to TARGET. In do_build_copy_constructor and
build_over_call we implement trivial copy of a class with tail padding using
assignment of character arrays, which is valid in normal code, but not in
constexpr evaluation. We don't need to worry about clobbering tail padding
in constexpr evaluation, so strip the type punning. */
static void
maybe_simplify_trivial_copy (tree &target, tree &init)
{
if (TREE_CODE (target) == MEM_REF
&& TREE_CODE (init) == MEM_REF
&& TREE_TYPE (target) == TREE_TYPE (init)
&& TREE_CODE (TREE_TYPE (target)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (target)) == unsigned_char_type_node)
{
target = build_fold_indirect_ref (TREE_OPERAND (target, 0));
init = build_fold_indirect_ref (TREE_OPERAND (init, 0));
}
}
/* Evaluate an INIT_EXPR or MODIFY_EXPR. */ /* Evaluate an INIT_EXPR or MODIFY_EXPR. */
static tree static tree
@ -3222,6 +3242,9 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* First we figure out where we're storing to. */ /* First we figure out where we're storing to. */
tree target = TREE_OPERAND (t, 0); tree target = TREE_OPERAND (t, 0);
maybe_simplify_trivial_copy (target, init);
tree type = TREE_TYPE (target); tree type = TREE_TYPE (target);
target = cxx_eval_constant_expression (ctx, target, target = cxx_eval_constant_expression (ctx, target,
true, true,

View File

@ -0,0 +1,14 @@
// PR c++/77945
// { dg-do compile { target c++11 } }
struct T
{
int x = 0;
bool y = 0;
constexpr T() {}
};
int main()
{
constexpr T t = (T{} = T{});
}