diff options
author | Jason Merrill <jason@redhat.com> | 2016-07-21 23:45:30 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-07-21 23:45:30 -0400 |
commit | d5ec842cde69dedaf9a447d7d7a00735c9b4da40 (patch) | |
tree | 23d12829ccddf066e337f8c344f90a7bd4d4de0c /gcc | |
parent | 4114e6b1fe8bb10a42ce56263ad42cba98138254 (diff) | |
download | gcc-d5ec842cde69dedaf9a447d7d7a00735c9b4da40.zip gcc-d5ec842cde69dedaf9a447d7d7a00735c9b4da40.tar.gz gcc-d5ec842cde69dedaf9a447d7d7a00735c9b4da40.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 8 | ||||
-rw-r--r-- | gcc/cp/method.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/tail-padding1.C | 18 |
4 files changed, 55 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0ba456c..3d3e85f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f929fb2..d917d9a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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, diff --git a/gcc/cp/method.c b/gcc/cp/method.c index cd8faaf..63aa53e 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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 { diff --git a/gcc/testsuite/g++.dg/torture/tail-padding1.C b/gcc/testsuite/g++.dg/torture/tail-padding1.C new file mode 100644 index 0000000..43e26ad --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/tail-padding1.C @@ -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 (); +} |