aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-10-29 16:27:01 +0100
committerJakub Jelinek <jakub@redhat.com>2020-10-29 16:27:01 +0100
commit815baade9a07d361b1daa1dcfbbda2a79f3ebb52 (patch)
treed009f7c200116f53e11dd3b94f040f55efe1b358 /gcc
parent40749db75caff2fed7b7053e0d1868feaa21bcb4 (diff)
downloadgcc-815baade9a07d361b1daa1dcfbbda2a79f3ebb52.zip
gcc-815baade9a07d361b1daa1dcfbbda2a79f3ebb52.tar.gz
gcc-815baade9a07d361b1daa1dcfbbda2a79f3ebb52.tar.bz2
c++: Diagnose constexpr delete [] new int; and delete new int[N]; [PR95808]
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. 2020-10-29 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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.c58
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C21
4 files changed, 80 insertions, 5 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 7ebdd30..37c836a 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2288,7 +2288,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
{
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 constexpr_ctx *ctx, tree t,
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++;
@@ -4605,7 +4645,9 @@ non_const_var_error (location_t loc, tree r)
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");
@@ -6365,8 +6407,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
&& 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));
@@ -6380,7 +6424,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
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 (var) == heap_uninit_identifier
+ ? heap_identifier : heap_vec_identifier);
TREE_TYPE (var)
= build_new_constexpr_heap_type (elt_type, cookie_size,
var_size);
@@ -6651,6 +6697,8 @@ find_heap_var_refs (tree *tp, int *walk_subtrees, void */*data*/)
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;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4f9038e..20774f8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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_MAX];
#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]
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ee3c353..39f56b8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4245,6 +4245,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}
};
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C
new file mode 100644
index 0000000..e97e7aa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new15.C
@@ -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 ();