diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-07-22 03:46:41 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-07-22 03:46:41 +0000 |
commit | 2edeadaf70591db084769ba4195360f84f9359c8 (patch) | |
tree | be716fb7df94d0805b4a78c91bd9e427b95e669d | |
parent | e7c0c81f9a9bf512fa2abb4044d3192593886002 (diff) | |
download | gcc-2edeadaf70591db084769ba4195360f84f9359c8.tar.gz |
PR c++/71913 - missing copy elision with new.
* call.c (unsafe_copy_elision_p): It's OK to elide when
initializing an unknown object.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-6-branch@238625 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/call.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/elide5.C | 27 |
3 files changed, 37 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8375aa5f270..a78862d538d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2016-07-21 Jason Merrill <jason@redhat.com> + + PR c++/71913 + * call.c (unsafe_copy_elision_p): It's OK to elide when + initializing an unknown object. + 2016-07-21 Jakub Jelinek <jakub@redhat.com> PR c++/71728 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 546f36dccc5..b87b4508629 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7179,10 +7179,11 @@ static bool unsafe_copy_elision_p (tree target, tree exp) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); - if (type == CLASSTYPE_AS_BASE (type)) + /* It's safe to elide the copy for a class with no tail padding. */ + if (tree_int_cst_equal (TYPE_SIZE (type), CLASSTYPE_SIZE (type))) return false; - if (!is_base_field_ref (target) - && resolves_to_fixed_type_p (target, NULL)) + /* It's safe to elide the copy if we aren't initializing a base object. */ + if (!is_base_field_ref (target)) return false; tree init = TARGET_EXPR_INITIAL (exp); /* build_compound_expr pushes COMPOUND_EXPR inside TARGET_EXPR. */ diff --git a/gcc/testsuite/g++.dg/init/elide5.C b/gcc/testsuite/g++.dg/init/elide5.C new file mode 100644 index 00000000000..0a9978ca661 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/elide5.C @@ -0,0 +1,27 @@ +// PR c++/71913 +// { dg-do link { target c++11 } } + +void* operator new(unsigned long, void* p) { return p; } + +struct IndirectReturn { + IndirectReturn() {} + // Undefined so we get a link error if the indirect return value is copied + IndirectReturn(const IndirectReturn&); + IndirectReturn& operator=(const IndirectReturn&) = delete; + ~IndirectReturn() {} +}; + +IndirectReturn foo() { return IndirectReturn(); } + +void bar(void* ptr) { + new (ptr) IndirectReturn(foo()); +} + +alignas (alignof (IndirectReturn)) +unsigned char c[sizeof(IndirectReturn)]; + +int main() +{ + bar(c); +} + |