diff options
author | Mark Mitchell <mark@codesourcery.com> | 2001-04-16 02:50:12 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2001-04-16 02:50:12 +0000 |
commit | 1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a (patch) | |
tree | 48199510d9ceeaf6551901883d22b7b6dcaa4389 | |
parent | 2406cfed9a14c49a295f00dd6758aa6aca1a86ed (diff) | |
download | gcc-1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a.zip gcc-1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a.tar.gz gcc-1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/init.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/delete8.C | 39 |
3 files changed, 52 insertions, 6 deletions
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 <mark@codesourcery.com> + + * 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 <mark@codesourcery.com> * 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 <mark@codesourcery.com> + +#include <stdlib.h> + +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; +} + |