c++, v2: Mark replaceable global operator new/delete with const std::nothrow_t& argument as DECL_IS_REPLACEABLE_OPERATOR [PR117370]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
Commit Message
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 <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.
Jakub
Comments
On 11/1/24 3:17 PM, Jakub Jelinek wrote:
> 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.
OK.
> 2024-11-01 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/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
>
@@ -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);
@@ -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
@@ -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);