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
This commit is contained in:
Ville Voutilainen 2017-03-21 08:36:22 +02:00 committed by Ville Voutilainen
parent 5b9e0383cc
commit ece3b7e65a
5 changed files with 86 additions and 1 deletions

View 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> 2017-03-20 Jason Merrill <jason@redhat.com>
PR c++/80096 - ICE with C++17 non-type auto. PR c++/80096 - ICE with C++17 non-type auto.

View File

@ -2707,6 +2707,21 @@ malloc_alignment ()
return MAX (max_align_t_align(), MALLOC_ABI_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 /* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for 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. */ So check for a null exception spec on the op new we just called. */
nothrow = TYPE_NOTHROW_P (TREE_TYPE (alloc_fn)); 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) if (cookie_size)
{ {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}