OSDN Git Service

* init.c (build_delete): Create a SAVE_EXPR for the address if
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 16 Apr 2001 02:50:12 +0000 (02:50 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 16 Apr 2001 02:50:12 +0000 (02:50 +0000)
we're going to use it more than once.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41371 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/g++.old-deja/g++.other/delete8.C [new file with mode: 0644]

index 53616a3..2487d9e 100644 (file)
@@ -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.
index f680ee0..93ff716 100644 (file)
@@ -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 (file)
index 0000000..1f884b7
--- /dev/null
@@ -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;
+}
+