]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c++/71913 - missing copy elision with new.
authorJason Merrill <jason@redhat.com>
Fri, 22 Jul 2016 03:41:44 +0000 (23:41 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 22 Jul 2016 03:41:44 +0000 (23:41 -0400)
* call.c (unsafe_copy_elision_p): It's OK to elide when
initializing an unknown object.

From-SVN: r238619

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/init/elide5.C [new file with mode: 0644]

index 5936ea64590b2c422c2c9efd6ab4babb7f0bead7..553c2ba8fc7aaa731de025cb2adf721616c096db 100644 (file)
@@ -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-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/71909
index d2de2abf503f507b94003eb1bf2a0efa425b2f8e..59dc3633a74c11d08cf59502c33ac8007d706ce3 100644 (file)
@@ -6757,10 +6757,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 (file)
index 0000000..0a9978c
--- /dev/null
@@ -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);
+}
+