* [PATCH] c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808]
@ 2020-10-16 9:42 Jakub Jelinek
2020-10-29 15:14 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2020-10-16 9:42 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
Hi!
This patch diagnoses delete [] new int; and delete new int[1]; in constexpr
contexts by remembering
IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun)) & OVL_OP_FLAG_VEC
from the operator new and checking it at operator delete time.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2020-10-16 Jakub Jelinek <jakub@redhat.com>
PR c++/95808
* cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_VEC_UNINIT_IDENTIFIER
and CPTI_HEAP_VEC_IDENTIFIER.
(heap_vec_uninit_identifier, heap_vec_identifier): Define.
* decl.c (initialize_predefined_identifiers): Initialize those
identifiers.
* constexpr.c (cxx_eval_call_expression): Reject array allocations
deallocated with non-array deallocation or non-array allocations
deallocated with array deallocation.
(non_const_var_error): Handle heap_vec_uninit_identifier and
heap_vec_identifier too.
(cxx_eval_constant_expression): Handle also heap_vec_uninit_identifier
and in that case during initialization replace it with
heap_vec_identifier.
(find_heap_var_refs): Handle heap_vec_uninit_identifier and
heap_vec_identifier too.
* g++.dg/cpp2a/constexpr-new15.C: New test.
--- gcc/cp/cp-tree.h.jj 2020-10-14 22:05:19.274858485 +0200
+++ gcc/cp/cp-tree.h 2020-10-15 16:29:12.136899207 +0200
@@ -178,6 +178,8 @@ enum cp_tree_index
CPTI_HEAP_UNINIT_IDENTIFIER,
CPTI_HEAP_IDENTIFIER,
CPTI_HEAP_DELETED_IDENTIFIER,
+ CPTI_HEAP_VEC_UNINIT_IDENTIFIER,
+ CPTI_HEAP_VEC_IDENTIFIER,
CPTI_LANG_NAME_C,
CPTI_LANG_NAME_CPLUSPLUS,
@@ -322,6 +324,8 @@ extern GTY(()) tree cp_global_trees[CPTI
#define heap_uninit_identifier cp_global_trees[CPTI_HEAP_UNINIT_IDENTIFIER]
#define heap_identifier cp_global_trees[CPTI_HEAP_IDENTIFIER]
#define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER]
+#define heap_vec_uninit_identifier cp_global_trees[CPTI_HEAP_VEC_UNINIT_IDENTIFIER]
+#define heap_vec_identifier cp_global_trees[CPTI_HEAP_VEC_IDENTIFIER]
#define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
#define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
--- gcc/cp/decl.c.jj 2020-10-14 22:05:19.293858210 +0200
+++ gcc/cp/decl.c 2020-10-15 16:30:05.690125490 +0200
@@ -4242,6 +4242,8 @@ initialize_predefined_identifiers (void)
{"heap uninit", &heap_uninit_identifier, cik_normal},
{"heap ", &heap_identifier, cik_normal},
{"heap deleted", &heap_deleted_identifier, cik_normal},
+ {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal},
+ {"heap []", &heap_vec_identifier, cik_normal},
{NULL, NULL, cik_normal}
};
--- gcc/cp/constexpr.c.jj 2020-10-01 11:16:36.390959542 +0200
+++ gcc/cp/constexpr.c 2020-10-15 17:02:31.036021476 +0200
@@ -2288,7 +2288,11 @@ cxx_eval_call_expression (const constexp
{
tree type = build_array_type_nelts (char_type_node,
tree_to_uhwi (arg0));
- tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
+ tree var = build_decl (loc, VAR_DECL,
+ (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ ? heap_vec_uninit_identifier
+ : heap_uninit_identifier,
type);
DECL_ARTIFICIAL (var) = 1;
TREE_STATIC (var) = 1;
@@ -2306,6 +2310,42 @@ cxx_eval_call_expression (const constexp
if (DECL_NAME (var) == heap_uninit_identifier
|| DECL_NAME (var) == heap_identifier)
{
+ if (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "array deallocation of object "
+ "allocated with non-array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
+ DECL_NAME (var) = heap_deleted_identifier;
+ ctx->global->values.remove (var);
+ ctx->global->heap_dealloc_count++;
+ return void_node;
+ }
+ else if (DECL_NAME (var) == heap_vec_uninit_identifier
+ || DECL_NAME (var) == heap_vec_identifier)
+ {
+ if ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
+ & OVL_OP_FLAG_VEC) == 0)
+ {
+ if (!ctx->quiet)
+ {
+ error_at (loc, "non-array deallocation of "
+ "object allocated with array "
+ "allocation");
+ inform (DECL_SOURCE_LOCATION (var),
+ "allocation performed here");
+ }
+ *non_constant_p = true;
+ return t;
+ }
DECL_NAME (var) = heap_deleted_identifier;
ctx->global->values.remove (var);
ctx->global->heap_dealloc_count++;
@@ -4591,7 +4631,9 @@ non_const_var_error (location_t loc, tre
auto_diagnostic_group d;
tree type = TREE_TYPE (r);
if (DECL_NAME (r) == heap_uninit_identifier
- || DECL_NAME (r) == heap_identifier)
+ || DECL_NAME (r) == heap_identifier
+ || DECL_NAME (r) == heap_vec_uninit_identifier
+ || DECL_NAME (r) == heap_vec_identifier)
{
error_at (loc, "the content of uninitialized storage is not usable "
"in a constant expression");
@@ -6351,8 +6393,10 @@ cxx_eval_constant_expression (const cons
&& TREE_TYPE (op) == ptr_type_node
&& TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
&& VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
- && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
- 0)) == heap_uninit_identifier)
+ && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_uninit_identifier
+ || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_vec_uninit_identifier))
{
tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
@@ -6366,7 +6410,10 @@ cxx_eval_constant_expression (const cons
elt_type = TREE_TYPE (TREE_TYPE (fld2));
cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
}
- DECL_NAME (var) = heap_identifier;
+ DECL_NAME (var)
+ = (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0)) == heap_uninit_identifier
+ ? heap_identifier : heap_vec_identifier);
TREE_TYPE (var)
= build_new_constexpr_heap_type (elt_type, cookie_size,
var_size);
@@ -6637,6 +6684,8 @@ find_heap_var_refs (tree *tp, int *walk_
if (VAR_P (*tp)
&& (DECL_NAME (*tp) == heap_uninit_identifier
|| DECL_NAME (*tp) == heap_identifier
+ || DECL_NAME (*tp) == heap_vec_uninit_identifier
+ || DECL_NAME (*tp) == heap_vec_identifier
|| DECL_NAME (*tp) == heap_deleted_identifier))
return *tp;
--- gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C.jj 2020-10-15 17:08:22.347946251 +0200
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C 2020-10-15 17:07:49.009427880 +0200
@@ -0,0 +1,21 @@
+// PR c++/95808
+// { dg-do compile { target c++20 } }
+
+constexpr
+bool foo ()
+{
+ int *p = new int; // { dg-message "allocation performed here" }
+ delete[] p; // { dg-error "array deallocation of object allocated with non-array allocation" }
+ return false;
+}
+
+constexpr
+bool bar ()
+{
+ int *p = new int[1]; // { dg-message "allocation performed here" }
+ delete p; // { dg-error "non-array deallocation of object allocated with array allocation" }
+ return false;
+}
+
+constexpr auto x = foo ();
+constexpr auto y = bar ();
Jakub
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808]
2020-10-16 9:42 [PATCH] c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808] Jakub Jelinek
@ 2020-10-29 15:14 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2020-10-29 15:14 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches
On 10/16/20 5:42 AM, Jakub Jelinek wrote:
> Hi!
>
> This patch diagnoses delete [] new int; and delete new int[1]; in constexpr
> contexts by remembering
> IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun)) & OVL_OP_FLAG_VEC
> from the operator new and checking it at operator delete time.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2020-10-16 Jakub Jelinek <jakub@redhat.com>
>
> PR c++/95808
> * cp-tree.h (enum cp_tree_index): Add CPTI_HEAP_VEC_UNINIT_IDENTIFIER
> and CPTI_HEAP_VEC_IDENTIFIER.
> (heap_vec_uninit_identifier, heap_vec_identifier): Define.
> * decl.c (initialize_predefined_identifiers): Initialize those
> identifiers.
> * constexpr.c (cxx_eval_call_expression): Reject array allocations
> deallocated with non-array deallocation or non-array allocations
> deallocated with array deallocation.
> (non_const_var_error): Handle heap_vec_uninit_identifier and
> heap_vec_identifier too.
> (cxx_eval_constant_expression): Handle also heap_vec_uninit_identifier
> and in that case during initialization replace it with
> heap_vec_identifier.
> (find_heap_var_refs): Handle heap_vec_uninit_identifier and
> heap_vec_identifier too.
>
> * g++.dg/cpp2a/constexpr-new15.C: New test.
>
> --- gcc/cp/cp-tree.h.jj 2020-10-14 22:05:19.274858485 +0200
> +++ gcc/cp/cp-tree.h 2020-10-15 16:29:12.136899207 +0200
> @@ -178,6 +178,8 @@ enum cp_tree_index
> CPTI_HEAP_UNINIT_IDENTIFIER,
> CPTI_HEAP_IDENTIFIER,
> CPTI_HEAP_DELETED_IDENTIFIER,
> + CPTI_HEAP_VEC_UNINIT_IDENTIFIER,
> + CPTI_HEAP_VEC_IDENTIFIER,
>
> CPTI_LANG_NAME_C,
> CPTI_LANG_NAME_CPLUSPLUS,
> @@ -322,6 +324,8 @@ extern GTY(()) tree cp_global_trees[CPTI
> #define heap_uninit_identifier cp_global_trees[CPTI_HEAP_UNINIT_IDENTIFIER]
> #define heap_identifier cp_global_trees[CPTI_HEAP_IDENTIFIER]
> #define heap_deleted_identifier cp_global_trees[CPTI_HEAP_DELETED_IDENTIFIER]
> +#define heap_vec_uninit_identifier cp_global_trees[CPTI_HEAP_VEC_UNINIT_IDENTIFIER]
> +#define heap_vec_identifier cp_global_trees[CPTI_HEAP_VEC_IDENTIFIER]
> #define lang_name_c cp_global_trees[CPTI_LANG_NAME_C]
> #define lang_name_cplusplus cp_global_trees[CPTI_LANG_NAME_CPLUSPLUS]
>
> --- gcc/cp/decl.c.jj 2020-10-14 22:05:19.293858210 +0200
> +++ gcc/cp/decl.c 2020-10-15 16:30:05.690125490 +0200
> @@ -4242,6 +4242,8 @@ initialize_predefined_identifiers (void)
> {"heap uninit", &heap_uninit_identifier, cik_normal},
> {"heap ", &heap_identifier, cik_normal},
> {"heap deleted", &heap_deleted_identifier, cik_normal},
> + {"heap [] uninit", &heap_vec_uninit_identifier, cik_normal},
> + {"heap []", &heap_vec_identifier, cik_normal},
> {NULL, NULL, cik_normal}
> };
>
> --- gcc/cp/constexpr.c.jj 2020-10-01 11:16:36.390959542 +0200
> +++ gcc/cp/constexpr.c 2020-10-15 17:02:31.036021476 +0200
> @@ -2288,7 +2288,11 @@ cxx_eval_call_expression (const constexp
> {
> tree type = build_array_type_nelts (char_type_node,
> tree_to_uhwi (arg0));
> - tree var = build_decl (loc, VAR_DECL, heap_uninit_identifier,
> + tree var = build_decl (loc, VAR_DECL,
> + (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
> + & OVL_OP_FLAG_VEC)
> + ? heap_vec_uninit_identifier
> + : heap_uninit_identifier,
> type);
> DECL_ARTIFICIAL (var) = 1;
> TREE_STATIC (var) = 1;
> @@ -2306,6 +2310,42 @@ cxx_eval_call_expression (const constexp
> if (DECL_NAME (var) == heap_uninit_identifier
> || DECL_NAME (var) == heap_identifier)
> {
> + if (IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
> + & OVL_OP_FLAG_VEC)
> + {
> + if (!ctx->quiet)
> + {
> + error_at (loc, "array deallocation of object "
> + "allocated with non-array "
> + "allocation");
> + inform (DECL_SOURCE_LOCATION (var),
> + "allocation performed here");
> + }
> + *non_constant_p = true;
> + return t;
> + }
> + DECL_NAME (var) = heap_deleted_identifier;
> + ctx->global->values.remove (var);
> + ctx->global->heap_dealloc_count++;
> + return void_node;
> + }
> + else if (DECL_NAME (var) == heap_vec_uninit_identifier
> + || DECL_NAME (var) == heap_vec_identifier)
> + {
> + if ((IDENTIFIER_OVL_OP_FLAGS (DECL_NAME (fun))
> + & OVL_OP_FLAG_VEC) == 0)
> + {
> + if (!ctx->quiet)
> + {
> + error_at (loc, "non-array deallocation of "
> + "object allocated with array "
> + "allocation");
> + inform (DECL_SOURCE_LOCATION (var),
> + "allocation performed here");
> + }
> + *non_constant_p = true;
> + return t;
> + }
> DECL_NAME (var) = heap_deleted_identifier;
> ctx->global->values.remove (var);
> ctx->global->heap_dealloc_count++;
> @@ -4591,7 +4631,9 @@ non_const_var_error (location_t loc, tre
> auto_diagnostic_group d;
> tree type = TREE_TYPE (r);
> if (DECL_NAME (r) == heap_uninit_identifier
> - || DECL_NAME (r) == heap_identifier)
> + || DECL_NAME (r) == heap_identifier
> + || DECL_NAME (r) == heap_vec_uninit_identifier
> + || DECL_NAME (r) == heap_vec_identifier)
> {
> error_at (loc, "the content of uninitialized storage is not usable "
> "in a constant expression");
> @@ -6351,8 +6393,10 @@ cxx_eval_constant_expression (const cons
> && TREE_TYPE (op) == ptr_type_node
> && TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR
> && VAR_P (TREE_OPERAND (TREE_OPERAND (op, 0), 0))
> - && DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
> - 0)) == heap_uninit_identifier)
> + && (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
> + 0)) == heap_uninit_identifier
> + || DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
> + 0)) == heap_vec_uninit_identifier))
> {
> tree var = TREE_OPERAND (TREE_OPERAND (op, 0), 0);
> tree var_size = TYPE_SIZE_UNIT (TREE_TYPE (var));
> @@ -6366,7 +6410,10 @@ cxx_eval_constant_expression (const cons
> elt_type = TREE_TYPE (TREE_TYPE (fld2));
> cookie_size = TYPE_SIZE_UNIT (TREE_TYPE (fld1));
> }
> - DECL_NAME (var) = heap_identifier;
> + DECL_NAME (var)
> + = (DECL_NAME (TREE_OPERAND (TREE_OPERAND (op, 0),
> + 0)) == heap_uninit_identifier
This can be
= (DECL_NAME (var) == heap_uninit_identifier
OK with that change.
> + ? heap_identifier : heap_vec_identifier);
> TREE_TYPE (var)
> = build_new_constexpr_heap_type (elt_type, cookie_size,
> var_size);
> @@ -6637,6 +6684,8 @@ find_heap_var_refs (tree *tp, int *walk_
> if (VAR_P (*tp)
> && (DECL_NAME (*tp) == heap_uninit_identifier
> || DECL_NAME (*tp) == heap_identifier
> + || DECL_NAME (*tp) == heap_vec_uninit_identifier
> + || DECL_NAME (*tp) == heap_vec_identifier
> || DECL_NAME (*tp) == heap_deleted_identifier))
> return *tp;
>
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C.jj 2020-10-15 17:08:22.347946251 +0200
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C 2020-10-15 17:07:49.009427880 +0200
> @@ -0,0 +1,21 @@
> +// PR c++/95808
> +// { dg-do compile { target c++20 } }
> +
> +constexpr
> +bool foo ()
> +{
> + int *p = new int; // { dg-message "allocation performed here" }
> + delete[] p; // { dg-error "array deallocation of object allocated with non-array allocation" }
> + return false;
> +}
> +
> +constexpr
> +bool bar ()
> +{
> + int *p = new int[1]; // { dg-message "allocation performed here" }
> + delete p; // { dg-error "non-array deallocation of object allocated with array allocation" }
> + return false;
> +}
> +
> +constexpr auto x = foo ();
> +constexpr auto y = bar ();
>
> Jakub
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-10-29 15:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-16 9:42 [PATCH] c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808] Jakub Jelinek
2020-10-29 15:14 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).