re PR c++/35878 ([LWG 2302] Useless NULL pointer check when constructing object)
authorVille Voutilainen <ville.voutilainen@gmail.com>
Tue, 21 Mar 2017 06:36:22 +0000 (08:36 +0200)
committerVille Voutilainen <ville@gcc.gnu.org>
Tue, 21 Mar 2017 06:36:22 +0000 (08:36 +0200)
gcc/

PR c++/35878
* cp/init.c (std_placement_new_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.

From-SVN: r246301

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

index 7dfa577..8264502 100644 (file)
@@ -1,3 +1,9 @@
+2017-03-21  Ville Voutilainen  <ville.voutilainen@gmail.com>
+
+       PR c++/35878
+       * cp/init.c (std_placement_new_fn_p): New.
+       (build_new_1): Call it.
+
 2017-03-20  Jason Merrill  <jason@redhat.com>
 
        PR c++/80096 - ICE with C++17 non-type auto.
index ebb1245..4ec26af 100644 (file)
@@ -2707,6 +2707,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 std_placement_new_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 true;
+    }
+  return false;
+}
+
 /* 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
@@ -3185,7 +3200,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 && !std_placement_new_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 (file)
index 0000000..b45c009
--- /dev/null
@@ -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 (file)
index 0000000..0664494
--- /dev/null
@@ -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 (file)
index 0000000..8a5614f
--- /dev/null
@@ -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);
+}