On 21 March 2017 at 02:46, Ville Voutilainen <ville.voutilai...@gmail.com> wrote: > On 21 March 2017 at 02:43, Ville Voutilainen > <ville.voutilai...@gmail.com> wrote: >> Hmm. I should either rename that function or flip its logic. Now it's >> a bit backwards. :) I'll flip its logic. > > In other words, see attached.
Let's call the function what it really is. 2017-03-21 Ville Voutilainen <ville.voutilai...@gmail.com> 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.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 8bfcbde..a0cd64c 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 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 @@ -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 && !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 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); +}