Message ID | 20201016094254.GE2176@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808] | expand |
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 >
--- 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 ();