]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Mark replaceable global operator new/delete with const std::nothrow_t& argument...
authorJakub Jelinek <jakub@redhat.com>
Tue, 5 Nov 2024 07:58:28 +0000 (08:58 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 5 Nov 2024 07:58:28 +0000 (08:58 +0100)
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.

gcc/cp/constexpr.cc
gcc/cp/cp-tree.h
gcc/cp/decl.cc

index c141c0a2844baba96d7749608790b2dbe26f3aac..71e6dc4ef3264e28071970fc17bab3d34ce91492 100644 (file)
@@ -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
index f98a1de42cae8738da7a2992112ff12d0082799a..92d1dba6a5c948311267bf956473c42927481940 100644 (file)
@@ -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);
index 0e4533c6faba591eb9cc2c1469ee7c51a0b889f1..b4e7ceefedb08e78def987f82aa14684b1aff9cb 100644 (file)
@@ -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);