From 1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 16 Apr 2001 02:50:12 +0000 Subject: init.c (build_delete): Create a SAVE_EXPR for the address if we're going to use it more than once. * init.c (build_delete): Create a SAVE_EXPR for the address if we're going to use it more than once. From-SVN: r41371 --- gcc/cp/ChangeLog | 5 ++++ gcc/cp/init.c | 14 +++++---- gcc/testsuite/g++.old-deja/g++.other/delete8.C | 39 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/delete8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 53616a3..2487d9e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2001-04-15 Mark Mitchell + + * init.c (build_delete): Create a SAVE_EXPR for the address if + we're going to use it more than once. + 2001-04-13 Mark Mitchell * cp-tree.h (DELTA2_FROM_PTRMEMFUNC): Remove. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index f680ee0..93ff716 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3155,7 +3155,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) { tree member; tree expr; - tree ref; if (addr == error_mark_node) return error_mark_node; @@ -3184,7 +3183,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) /* throw away const and volatile on target type of addr */ addr = convert_force (build_pointer_type (type), addr, 0); - ref = build_indirect_ref (addr, NULL_PTR); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3209,8 +3207,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) addr = save_expr (addr); addr = convert_force (build_pointer_type (type), addr, 0); - - ref = build_indirect_ref (addr, NULL_PTR); } my_friendly_assert (IS_AGGR_TYPE (type), 220); @@ -3239,6 +3235,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) delete'. */ if (use_global_delete && auto_delete == sfk_deleting_destructor) { + /* We will use ADDR multiple times so we must save it. */ + addr = save_expr (addr); /* Delete the object. */ do_delete = build_builtin_delete_call (addr); /* Otherwise, treat this like a complete object destructor @@ -3251,7 +3249,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type)) && auto_delete == sfk_deleting_destructor) { - /* Buidl the call. */ + /* We will use ADDR multiple times so we must save it. */ + addr = save_expr (addr); + /* Build the call. */ do_delete = build_op_delete_call (DELETE_EXPR, addr, c_sizeof_nowarn (type), @@ -3261,7 +3261,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) auto_delete = sfk_complete_destructor; } - expr = build_dtor_call (ref, auto_delete, flags); + expr = build_dtor_call (build_indirect_ref (addr, NULL_PTR), + auto_delete, flags); if (do_delete) expr = build (COMPOUND_EXPR, void_type_node, expr, do_delete); @@ -3285,6 +3286,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type); tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE; tree exprstmt = NULL_TREE; + tree ref = build_indirect_ref (addr, NULL_PTR); /* Set this again before we call anything, as we might get called recursively. */ diff --git a/gcc/testsuite/g++.old-deja/g++.other/delete8.C b/gcc/testsuite/g++.old-deja/g++.other/delete8.C new file mode 100644 index 0000000..1f884b7 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/delete8.C @@ -0,0 +1,39 @@ +// Origin: Mark Mitchell + +#include + +struct S { + ~S (); +}; + +bool flag; +S* s1; +S* s2; + +void* operator new (size_t s) +{ + return malloc (s); +} + +void operator delete (void* p) +{ + if (flag && p != s2) + abort (); +} + +S::~S () { + if (this != s2) + abort (); + s1 = 0; +} + +int main () { + s2 = new S; + s1 = s2; + // Turn on the check in `operator delete'. + flag = true; + delete s1; + // Turn it off again so that normal shutdown code works. + flag = false; +} + -- cgit v1.1