mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-12-21 18:15:06 +08:00
call.c (build_over_call): Check unsafe_copy_elision_p even for trivial constructors.
* 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. From-SVN: r238620
This commit is contained in:
parent
4114e6b1fe
commit
d5ec842cde
@ -1,3 +1,10 @@
|
||||
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
|
||||
|
@ -7271,6 +7271,9 @@ is_base_field_ref (tree t)
|
||||
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;
|
||||
@ -7726,9 +7729,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|
||||
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,
|
||||
|
@ -542,14 +542,32 @@ do_build_copy_constructor (tree fndecl)
|
||||
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
|
||||
{
|
||||
|
18
gcc/testsuite/g++.dg/torture/tail-padding1.C
Normal file
18
gcc/testsuite/g++.dg/torture/tail-padding1.C
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user