On Fri, Nov 01, 2024 at 12:28:52PM -0400, Jason Merrill wrote:
> Can this block be
> 
> if (aligned_allocation_fn_p (decl))
>   args = TREE_CHAIN (args);
> 
> ?

Yes.

> > +                 && TREE_CODE (t) == RECORD_TYPE
> > +                 && DECL_NAMESPACE_STD_P (CP_TYPE_CONTEXT (t))
> > +                 && TYPE_NAME (t)
> > +                 && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
> > +                 && DECL_NAME (TYPE_NAME (t))
> > +                 && id_equal (DECL_NAME (TYPE_NAME (t)), "nothrow_t"))
> 
> Let's factor is_std_allocator into a function taking a const char * and use
> that here as well.

So like this?
I've verified on #include <new> with -std=c++23 it marks exactly 8 operators
which is the expected count.

2024-11-01  Jakub Jelinek  <ja...@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/cp-tree.h.jj 2024-11-01 19:32:12.961053085 +0100
+++ gcc/cp/cp-tree.h    2024-11-01 20:10:18.246350835 +0100
@@ -8706,6 +8706,7 @@ extern bool is_rvalue_constant_expressio
 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);
--- gcc/cp/constexpr.cc.jj      2024-10-25 10:00:29.407768730 +0200
+++ gcc/cp/constexpr.cc 2024-11-01 20:12:04.835825528 +0100
@@ -2363,22 +2363,30 @@ is_std_construct_at (const constexpr_cal
          && 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
--- gcc/cp/decl.cc.jj   2024-10-31 21:17:07.059018373 +0100
+++ gcc/cp/decl.cc      2024-11-01 20:12:48.506200598 +0100
@@ -16191,6 +16191,36 @@ grok_op_properties (tree decl, bool comp
            }
        }
 
+      /* 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);


        Jakub

Reply via email to