Skip to content

Commit c1bbad0

Browse files
committed
c++: Mark replaceable global operator new/delete with const std::nothrow_t& argument as DECL_IS_REPLACEABLE_OPERATOR [PR117370]
cxx_init_decl_processing predeclares 12 out of the 20 replaceable global new/delete operators and sets DECL_IS_REPLACEABLE_OPERATOR on those. But it doesn't handle the remaining 8, in particular void* operator new(std::size_t, const std::nothrow_t&) noexcept; void* operator new[](std::size_t, const std::nothrow_t&) noexcept; void operator delete(void*, const std::nothrow_t&) noexcept; void operator delete[](void*, const std::nothrow_t&) noexcept; void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) noexcept; void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) noexcept; void operator delete(void*, std::align_val_t, const std::nothrow_t&) noexcept; void operator delete[](void*, std::align_val_t, const std::nothrow_t&) noexcept; The following patch sets that flag during grok_op_properties for those, so that they don't need to be predeclared. The patch doesn't fix the whole PR, as some work is needed on the CDDCE side too, unlike the throwing operator new case the if (ptr) conditional around operator delete isn't removed by VRP and so we need to handle conditional delete for unconditional new. 2024-11-05 Jakub Jelinek <[email protected]> PR c++/117370 * cp-tree.h (is_std_class): Declare. * constexpr.cc (is_std_class): New function. (is_std_allocator): Use it. * decl.cc (grok_op_properties): Mark global replaceable operator new/delete operators with const std::nothrow_t & last argument with DECL_IS_REPLACEABLE_OPERATOR.
1 parent ea46a21 commit c1bbad0

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

gcc/cp/constexpr.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,22 +2363,30 @@ is_std_construct_at (const constexpr_call *call)
23632363
&& is_std_construct_at (call->fundef->decl));
23642364
}
23652365

2366-
/* True if CTX is an instance of std::allocator. */
2366+
/* True if CTX is an instance of std::NAME class. */
23672367

23682368
bool
2369-
is_std_allocator (tree ctx)
2369+
is_std_class (tree ctx, const char *name)
23702370
{
23712371
if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
23722372
return false;
23732373

23742374
tree decl = TYPE_MAIN_DECL (ctx);
2375-
tree name = DECL_NAME (decl);
2376-
if (name == NULL_TREE || !id_equal (name, "allocator"))
2375+
tree dname = DECL_NAME (decl);
2376+
if (dname == NULL_TREE || !id_equal (dname, name))
23772377
return false;
23782378

23792379
return decl_in_std_namespace_p (decl);
23802380
}
23812381

2382+
/* True if CTX is an instance of std::allocator. */
2383+
2384+
bool
2385+
is_std_allocator (tree ctx)
2386+
{
2387+
return is_std_class (ctx, "allocator");
2388+
}
2389+
23822390
/* Return true if FNDECL is std::allocator<T>::{,de}allocate. */
23832391

23842392
static inline bool

gcc/cp/cp-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8706,6 +8706,7 @@ extern bool is_rvalue_constant_expression (tree);
87068706
extern bool is_nondependent_constant_expression (tree);
87078707
extern bool is_nondependent_static_init_expression (tree);
87088708
extern bool is_static_init_expression (tree);
8709+
extern bool is_std_class (tree, const char *);
87098710
extern bool is_std_allocator (tree);
87108711
extern bool potential_rvalue_constant_expression (tree);
87118712
extern bool require_potential_constant_expression (tree);

gcc/cp/decl.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16191,6 +16191,36 @@ grok_op_properties (tree decl, bool complain)
1619116191
}
1619216192
}
1619316193

16194+
/* Check for replaceable global new/delete operators with
16195+
const std::nothrow_t & last argument, other replaceable global
16196+
new/delete operators are marked in cxx_init_decl_processing. */
16197+
if (CP_DECL_CONTEXT (decl) == global_namespace)
16198+
{
16199+
tree args = argtypes;
16200+
if (args
16201+
&& args != void_list_node
16202+
&& same_type_p (TREE_VALUE (args),
16203+
(op_flags & OVL_OP_FLAG_DELETE)
16204+
? ptr_type_node : size_type_node))
16205+
{
16206+
args = TREE_CHAIN (args);
16207+
if (aligned_allocation_fn_p (decl))
16208+
args = TREE_CHAIN (args);
16209+
if (args
16210+
&& args != void_list_node
16211+
&& TREE_CHAIN (args) == void_list_node)
16212+
{
16213+
tree t = TREE_VALUE (args);
16214+
if (TYPE_REF_P (t)
16215+
&& !TYPE_REF_IS_RVALUE (t)
16216+
&& (t = TREE_TYPE (t))
16217+
&& TYPE_QUALS (t) == TYPE_QUAL_CONST
16218+
&& is_std_class (t, "nothrow_t"))
16219+
DECL_IS_REPLACEABLE_OPERATOR (decl) = 1;
16220+
}
16221+
}
16222+
}
16223+
1619416224
if (op_flags & OVL_OP_FLAG_DELETE)
1619516225
{
1619616226
DECL_SET_IS_OPERATOR_DELETE (decl, true);

0 commit comments

Comments
 (0)