aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-11-05 08:58:28 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2024-11-05 08:58:28 +0100
commitc1bbad07c8686c858ea58ffdb9db8f964bf485c6 (patch)
tree6498873720d75cfac2cde4599529df9b01676a72
parentea46a216d48597b220ae69e79f6513c763f953be (diff)
downloadgcc-c1bbad07c8686c858ea58ffdb9db8f964bf485c6.zip
gcc-c1bbad07c8686c858ea58ffdb9db8f964bf485c6.tar.gz
gcc-c1bbad07c8686c858ea58ffdb9db8f964bf485c6.tar.bz2
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 <jakub@redhat.com> 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.
-rw-r--r--gcc/cp/constexpr.cc16
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.cc30
3 files changed, 43 insertions, 4 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index c141c0a..71e6dc4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2363,22 +2363,30 @@ is_std_construct_at (const constexpr_call *call)
&& is_std_construct_at (call->fundef->decl));
}
-/* True if CTX is an instance of std::allocator. */
+/* True if CTX is an instance of std::NAME class. */
bool
-is_std_allocator (tree ctx)
+is_std_class (tree ctx, const char *name)
{
if (ctx == NULL_TREE || !CLASS_TYPE_P (ctx) || !TYPE_MAIN_DECL (ctx))
return false;
tree decl = TYPE_MAIN_DECL (ctx);
- tree name = DECL_NAME (decl);
- if (name == NULL_TREE || !id_equal (name, "allocator"))
+ tree dname = DECL_NAME (decl);
+ if (dname == NULL_TREE || !id_equal (dname, name))
return false;
return decl_in_std_namespace_p (decl);
}
+/* True if CTX is an instance of std::allocator. */
+
+bool
+is_std_allocator (tree ctx)
+{
+ return is_std_class (ctx, "allocator");
+}
+
/* Return true if FNDECL is std::allocator<T>::{,de}allocate. */
static inline bool
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f98a1de..92d1dba 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8706,6 +8706,7 @@ extern bool is_rvalue_constant_expression (tree);
extern bool is_nondependent_constant_expression (tree);
extern bool is_nondependent_static_init_expression (tree);
extern bool is_static_init_expression (tree);
+extern bool is_std_class (tree, const char *);
extern bool is_std_allocator (tree);
extern bool potential_rvalue_constant_expression (tree);
extern bool require_potential_constant_expression (tree);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 0e4533c..b4e7cee 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -16191,6 +16191,36 @@ grok_op_properties (tree decl, bool complain)
}
}
+ /* Check for replaceable global new/delete operators with
+ const std::nothrow_t & last argument, other replaceable global
+ new/delete operators are marked in cxx_init_decl_processing. */
+ if (CP_DECL_CONTEXT (decl) == global_namespace)
+ {
+ tree args = argtypes;
+ if (args
+ && args != void_list_node
+ && same_type_p (TREE_VALUE (args),
+ (op_flags & OVL_OP_FLAG_DELETE)
+ ? ptr_type_node : size_type_node))
+ {
+ args = TREE_CHAIN (args);
+ if (aligned_allocation_fn_p (decl))
+ args = TREE_CHAIN (args);
+ if (args
+ && args != void_list_node
+ && TREE_CHAIN (args) == void_list_node)
+ {
+ tree t = TREE_VALUE (args);
+ if (TYPE_REF_P (t)
+ && !TYPE_REF_IS_RVALUE (t)
+ && (t = TREE_TYPE (t))
+ && TYPE_QUALS (t) == TYPE_QUAL_CONST
+ && is_std_class (t, "nothrow_t"))
+ DECL_IS_REPLACEABLE_OPERATOR (decl) = 1;
+ }
+ }
+ }
+
if (op_flags & OVL_OP_FLAG_DELETE)
{
DECL_SET_IS_OPERATOR_DELETE (decl, true);