[C++] PR c++/35878

Submitted by ville on March 21, 2017, 12:36 a.m.

Details

Message ID CAFk2RUb84L5=Q9_DKnB9jSKw1+=FishTeaWU9x+s_9WChZoccQ@mail.gmail.com
State New
Headers show

Commit Message

ville March 21, 2017, 12:36 a.m.
On 21 March 2017 at 01:44, Jason Merrill <jason@redhat.com> wrote:
>> It looks strange to me. Why not change the definition of check_new instead
>> of changing the condition that uses it?
>
> Agreed.  Also, let's factor the new tests out into a function, say
> non_allocating_fn_p.

This also conveniently let's me provide a ChangeLog that reads like a
Real Front-End
Developer would've written it. :) New tests re-tested on Linux-x64,
running full suite
on Linux-PPC64.

2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>

    gcc/

    PR c++/35878
    * cp/init.c (non_allocating_fn_p): New.
    (build_new_1): Call it.

    testsuite/

    PR c++/35878
    * g++.dg/init/pr35878_1.C: New.
    * g++.dg/init/pr35878_2.C: Likewise.
    * g++.dg/init/pr35878_3.C: Likewise.

Comments

ville March 21, 2017, 12:43 a.m.
On 21 March 2017 at 02:36, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 21 March 2017 at 01:44, Jason Merrill <jason@redhat.com> wrote:
>>> It looks strange to me. Why not change the definition of check_new instead
>>> of changing the condition that uses it?
>>
>> Agreed.  Also, let's factor the new tests out into a function, say
>> non_allocating_fn_p.
>
> This also conveniently let's me provide a ChangeLog that reads like a
> Real Front-End
> Developer would've written it. :) New tests re-tested on Linux-x64,
> running full suite
> on Linux-PPC64.


Hmm. I should either rename that function or flip its logic. Now it's
a bit backwards. :) I'll flip its logic.

Patch hide | download patch | download mbox

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8bfcbde..dc5a5f7 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2693,6 +2693,21 @@  malloc_alignment ()
   return MAX (max_align_t_align(), MALLOC_ABI_ALIGNMENT);
 }
 
+/* Determine whether an allocation function is a namespace-scope
+   non-replaceable placement new function. See DR 1748.
+   TODO: Enable in all standard modes.  */
+static bool non_allocating_fn_p (tree alloc_fn)
+{
+  if ((cxx_dialect > cxx14) && DECL_NAMESPACE_SCOPE_P (alloc_fn))
+    {
+      tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
+      if ((TREE_VALUE (first_arg) == ptr_type_node)
+	  && TREE_CHAIN (first_arg) == void_list_node)
+	return false;
+    }
+  return true;
+}
+
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
@@ -3171,7 +3186,8 @@  build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      So check for a null exception spec on the op new we just called.  */
 
   nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn));
-  check_new = (flag_check_new || nothrow);
+  check_new = flag_check_new
+    || (nothrow && non_allocating_fn_p (alloc_fn));
 
   if (cookie_size)
     {
diff --git a/gcc/testsuite/g++.dg/init/pr35878_1.C b/gcc/testsuite/g++.dg/init/pr35878_1.C
new file mode 100644
index 0000000..b45c009
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_1.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++11" }
+// { dg-do compile }
+// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}
diff --git a/gcc/testsuite/g++.dg/init/pr35878_2.C b/gcc/testsuite/g++.dg/init/pr35878_2.C
new file mode 100644
index 0000000..0664494
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_2.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++17 -fcheck-new" }
+// { dg-do compile }
+// { dg-final { scan-assembler "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}
diff --git a/gcc/testsuite/g++.dg/init/pr35878_3.C b/gcc/testsuite/g++.dg/init/pr35878_3.C
new file mode 100644
index 0000000..8a5614f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/pr35878_3.C
@@ -0,0 +1,21 @@ 
+// { dg-options "-O2 --std=gnu++17" }
+// { dg-do compile }
+// { dg-final { scan-assembler-not "test.*%rdi, %rdi" { target i?86-*-* x86_64-*-* } } }
+#include <new>
+#include <utility>
+
+struct s1{
+  int a;
+  int b;
+  int c;
+};
+
+void f1 (s1 * v, s1&& s)
+{
+	new (v) s1(std::move(s));
+}
+
+void f2 (s1 * v, s1&& s)
+{
+	*v = std::move(s);
+}