Tested x86_64-pc-linux-gnu, applying to trunk. -- 8< --
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. --- gcc/cp/init.cc | 9 ++++++++- gcc/cp/tree.cc | 6 +++++- gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/array-prvalue3.C diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 906e401974c..52396d87a8c 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 4d87661b4ad..0485a618c6c 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 00000000000..f264e46084a --- /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 } +} base-commit: 0b3b6a8df77b0ae15078402ea5fb933d6fccd585 -- 2.44.0