aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2001-04-16 02:50:12 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2001-04-16 02:50:12 +0000
commit1b4a93f79b44e6cffbd43cbdfa0f649b9b43158a (patch)
tree48199510d9ceeaf6551901883d22b7b6dcaa4389
parent2406cfed9a14c49a295f00dd6758aa6aca1a86ed (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/cp/init.c14
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/delete8.C39
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;
+}
+