aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-05-22 18:41:27 -0400
committerJason Merrill <jason@redhat.com>2024-05-23 16:23:39 -0400
commited63cd2aa5b114565fe5499c3a6bf8da5e8e48ba (patch)
tree06272b6b470f3791b6a43b1a09e254e5609a141a /gcc
parent0b3b6a8df77b0ae15078402ea5fb933d6fccd585 (diff)
downloadgcc-ed63cd2aa5b114565fe5499c3a6bf8da5e8e48ba.zip
gcc-ed63cd2aa5b114565fe5499c3a6bf8da5e8e48ba.tar.gz
gcc-ed63cd2aa5b114565fe5499c3a6bf8da5e8e48ba.tar.bz2
c++: deleting array temporary [PR115187]
Decaying the array temporary to a pointer and then deleting that crashes in verify_gimple_stmt, because the TARGET_EXPR is first evaluated inside the TRY_FINALLY_EXPR, but the cleanup point is outside. Fixed by using get_target_expr instead of save_expr. I also adjust the stabilize_expr comment to prevent me from again thinking it's a suitable replacement. PR c++/115187 gcc/cp/ChangeLog: * init.cc (build_delete): Use get_target_expr instead of save_expr. * tree.cc (stabilize_expr): Update comment. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/array-prvalue3.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.cc9
-rw-r--r--gcc/cp/tree.cc6
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C8
3 files changed, 21 insertions, 2 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 906e401..52396d8 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -5228,9 +5228,13 @@ build_delete (location_t loc, tree otype, tree addr,
addr = convert_force (build_pointer_type (type), addr, 0, complain);
}
+ tree addr_expr = NULL_TREE;
if (deleting)
/* We will use ADDR multiple times so we must save it. */
- addr = save_expr (addr);
+ {
+ addr_expr = get_target_expr (addr);
+ addr = TARGET_EXPR_SLOT (addr_expr);
+ }
bool virtual_p = false;
if (type_build_dtor_call (type))
@@ -5349,6 +5353,9 @@ build_delete (location_t loc, tree otype, tree addr,
if (!integer_nonzerop (ifexp))
expr = build3 (COND_EXPR, void_type_node, ifexp, expr, void_node);
+ if (addr_expr)
+ expr = cp_build_compound_expr (addr_expr, expr, tf_none);
+
protected_set_expr_location (expr, loc);
return expr;
}
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 4d87661..0485a61 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -5924,7 +5924,11 @@ decl_storage_duration (tree decl)
*INITP) an expression that will perform the pre-evaluation. The
value returned by this function is a side-effect free expression
equivalent to the pre-evaluated expression. Callers must ensure
- that *INITP is evaluated before EXP. */
+ that *INITP is evaluated before EXP.
+
+ Note that if EXPR is a glvalue, the return value is a glvalue denoting the
+ same address; this function does not guard against modification of the
+ stored value like save_expr or get_target_expr do. */
tree
stabilize_expr (tree exp, tree* initp)
diff --git a/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
new file mode 100644
index 0000000..f264e46
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C
@@ -0,0 +1,8 @@
+// PR c++/115187
+// { dg-do compile { target c++17 } }
+
+void f() {
+ using T = int[2];
+ delete T{}; // { dg-warning "deleting array" }
+ // { dg-warning "unallocated object" "" { target *-*-* } .-1 }
+}