On 20 March 2017 at 04:27, Jason Merrill <[email protected]> wrote:
> On Sun, Mar 19, 2017 at 6:19 PM, Ville Voutilainen
> <[email protected]> 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 <[email protected]>
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);
+}