+2016-07-21 Jason Merrill <jason@redhat.com>
+
+ * call.c (build_over_call): Check unsafe_copy_elision_p even for
+ trivial constructors.
+ * method.c (do_build_copy_constructor): Don't copy tail padding
+ even in a trivial constructor.
+
2016-07-21 Jakub Jelinek <jakub@redhat.com>
PR c++/71728
static bool
unsafe_copy_elision_p (tree target, tree exp)
{
+ /* Copy elision only happens with a TARGET_EXPR. */
+ if (TREE_CODE (exp) != TARGET_EXPR)
+ return false;
tree type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
if (type == CLASSTYPE_AS_BASE (type))
return false;
else if (trivial)
return force_target_expr (DECL_CONTEXT (fn), arg, complain);
}
- else if (trivial
- || (TREE_CODE (arg) == TARGET_EXPR
- && !unsafe_copy_elision_p (fa, arg)))
+ else if ((trivial || TREE_CODE (arg) == TARGET_EXPR)
+ && !unsafe_copy_elision_p (fa, arg))
{
tree to = cp_stabilize_reference (cp_build_indirect_ref (fa,
RO_NULL,
if (!inh)
parm = convert_from_reference (parm);
- if (trivial
- && is_empty_class (current_class_type))
- /* Don't copy the padding byte; it might not have been allocated
- if *this is a base subobject. */;
- else if (trivial)
+ if (trivial)
{
- tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
- finish_expr_stmt (t);
+ if (is_empty_class (current_class_type))
+ /* Don't copy the padding byte; it might not have been allocated
+ if *this is a base subobject. */;
+ else if (tree_int_cst_equal (TYPE_SIZE (current_class_type),
+ CLASSTYPE_SIZE (current_class_type)))
+ {
+ tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
+ finish_expr_stmt (t);
+ }
+ else
+ {
+ /* We must only copy the non-tail padding parts. */
+ tree base_size = CLASSTYPE_SIZE_UNIT (current_class_type);
+ base_size = size_binop (MINUS_EXPR, base_size, size_int (1));
+ tree array_type = build_array_type (unsigned_char_type_node,
+ build_index_type (base_size));
+ tree alias_set = build_int_cst (TREE_TYPE (current_class_ptr), 0);
+ tree lhs = build2 (MEM_REF, array_type,
+ current_class_ptr, alias_set);
+ tree rhs = build2 (MEM_REF, array_type,
+ TREE_OPERAND (parm, 0), alias_set);
+ tree t = build2 (INIT_EXPR, void_type_node, lhs, rhs);
+ finish_expr_stmt (t);
+ }
}
else
{
--- /dev/null
+// Test that initializing a non-POD base with a trivial copy ctor doesn't
+// clobber tail padding.
+
+// { dg-do run }
+
+struct X { ~X() {} int n; char d; };
+struct Y { Y(); char c[3]; };
+struct Z : X, virtual Y { Z(); };
+
+X f() { X nrvo; __builtin_memset(&nrvo, 0, sizeof(X)); return nrvo; }
+Z::Z() : Y(), X(f()) {}
+Y::Y() { c[0] = 1; }
+
+int main() {
+ Z z;
+ if (z.c[0] != 1)
+ __builtin_abort ();
+}