From ece3b7e65aed085cfc73a7e84ceb4a25c2683054 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Tue, 21 Mar 2017 08:36:22 +0200 Subject: [PATCH] re PR c++/35878 ([LWG 2302] Useless NULL pointer check when constructing object) 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 | 6 ++++++ gcc/cp/init.c | 18 +++++++++++++++++- gcc/testsuite/g++.dg/init/pr35878_1.C | 21 +++++++++++++++++++++ gcc/testsuite/g++.dg/init/pr35878_2.C | 21 +++++++++++++++++++++ gcc/testsuite/g++.dg/init/pr35878_3.C | 21 +++++++++++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/init/pr35878_1.C create mode 100644 gcc/testsuite/g++.dg/init/pr35878_2.C create mode 100644 gcc/testsuite/g++.dg/init/pr35878_3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7dfa57771ad..8264502e050 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2017-03-21 Ville Voutilainen + + PR c++/35878 + * cp/init.c (std_placement_new_fn_p): New. + (build_new_1): Call it. + 2017-03-20 Jason Merrill PR c++/80096 - ICE with C++17 non-type auto. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ebb1245d9c2..4ec26afa235 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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 **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 00000000000..b45c0097a93 --- /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 +#include + +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 00000000000..066449419b9 --- /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 +#include + +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 00000000000..8a5614f12ff --- /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 +#include + +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); +} -- 2.11.4.GIT