On 20 March 2017 at 04:27, Jason Merrill <ja...@redhat.com> wrote:
> On Sun, Mar 19, 2017 at 6:19 PM, Ville Voutilainen
> <ville.voutilai...@gmail.com> wrote:
>> I ran the tests for g++.dg/init thus far. Does this patch make sense?
>
> The condition needs to be a lot more specific: DR 1748 only applies to
> the non-allocating forms in [new.delete.placement], not to other
> placement allocation functions.

Round 2:

The new tests tested on Linux-x64, finishing testing with the full suite on
Linux-PPC64.

2017-03-20  Ville Voutilainen  <ville.voutilai...@gmail.com>

    gcc/

    PR c++/35878
    * cp/init.c (build_new_1): Don't do a null check for
    a namespace-scope non-replaceable placement new
    in C++17 mode unless -fcheck-new is provided.

    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.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8bfcbde..cd34141 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3450,7 +3450,21 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, 
tree nelts,
     rval = TARGET_EXPR_INITIAL (alloc_expr);
   else
     {
-      if (check_new)
+      /* See DR 1748. Skip the null check in C++17 mode for non-replaceable
+        namespace-scope placement new forms unless the user explicitly
+        asks for the check.
+        TODO: Skip the null check in other modes as well.  */
+      if ((check_new && (cxx_dialect <= cxx14))
+         || flag_check_new
+         || ((cxx_dialect > cxx14)
+             && !(DECL_NAMESPACE_SCOPE_P (alloc_fn)
+                  && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)))
+                  && (TREE_VALUE (TREE_CHAIN
+                                  (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))))
+                      == ptr_type_node)
+                  && (TREE_CHAIN (TREE_CHAIN
+                                  (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))))
+                      == void_list_node))))
        {
          tree ifexp = cp_build_binary_op (input_location,
                                           NE_EXPR, alloc_node,
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);
+}

Reply via email to