OSDN Git Service

PR c++/15097
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Sep 2007 01:24:59 +0000 (01:24 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Sep 2007 01:24:59 +0000 (01:24 +0000)
        * init.c (build_delete): Use build_headof to get the address of the
        complete object if we aren't using the deleting destructor.
        * rtti.c (build_headof): No longer static.
        * cp-tree.h: Declare it.

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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/rtti.c
gcc/testsuite/g++.dg/init/delete2.C [new file with mode: 0644]

index b8fb971..a32ecdb 100644 (file)
@@ -1,3 +1,11 @@
+2007-09-05  Jason Merrill  <jason@redhat.com>
+
+       PR c++/15097
+       * init.c (build_delete): Use build_headof to get the address of the
+       complete object if we aren't using the deleting destructor.
+       * rtti.c (build_headof): No longer static.
+       * cp-tree.h: Declare it.
+
 2007-09-06  Jakub Jelinek  <jakub@redhat.com>
 
        * decl.c (duplicate_decls): Set TREE_NOTHROW on __builtin_XX
@@ -28,6 +36,9 @@
 
 2007-09-04  Jason Merrill  <jason@redhat.com>
 
+       * except.c (initialize_handler_parm): Use
+       fold_build_cleanup_point_expr.
+
        PR c++/31419
        * call.c (reference_binding): Don't look for user-defined conversions
        to the same type.
index 71f401f..9bd8ed2 100644 (file)
@@ -4481,6 +4481,7 @@ extern void init_rtti_processing          (void);
 extern tree build_typeid                       (tree);
 extern tree get_tinfo_decl                     (tree);
 extern tree get_typeid                         (tree);
+extern tree build_headof                       (tree);
 extern tree build_dynamic_cast                 (tree, tree);
 extern void emit_support_tinfos                        (void);
 extern bool emit_tinfo_decl                    (tree);
index b46d687..1aa732c 100644 (file)
@@ -2866,6 +2866,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
     }
   else
     {
+      tree head = NULL_TREE;
       tree do_delete = NULL_TREE;
       tree ifexp;
 
@@ -2879,8 +2880,9 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        {
          /* We will use ADDR multiple times so we must save it.  */
          addr = save_expr (addr);
+         head = get_target_expr (build_headof (addr));
          /* Delete the object.  */
-         do_delete = build_builtin_delete_call (addr);
+         do_delete = build_builtin_delete_call (head);
          /* Otherwise, treat this like a complete object destructor
             call.  */
          auto_delete = sfk_complete_destructor;
@@ -2919,6 +2921,10 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       if (do_delete)
        expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete);
 
+      /* We need to calculate this before the dtor changes the vptr.  */
+      if (head)
+       expr = build2 (COMPOUND_EXPR, void_type_node, head, expr);
+
       if (flags & LOOKUP_DESTRUCTOR)
        /* Explicit destructor call; don't check for null pointer.  */
        ifexp = integer_one_node;
index 8253a28..9d2ffdf 100644 (file)
@@ -101,7 +101,6 @@ VEC(tree,gc) *unemitted_tinfo_decls;
    and are generated as needed. */
 static GTY (()) VEC(tinfo_s,gc) *tinfo_descs;
 
-static tree build_headof (tree);
 static tree ifnonnull (tree, tree);
 static tree tinfo_name (tree);
 static tree build_dynamic_cast_1 (tree, tree);
@@ -155,7 +154,7 @@ init_rtti_processing (void)
    virtual functions (TYPE_POLYMORPHIC_P), else just return the
    expression.  */
 
-static tree
+tree
 build_headof (tree exp)
 {
   tree type = TREE_TYPE (exp);
diff --git a/gcc/testsuite/g++.dg/init/delete2.C b/gcc/testsuite/g++.dg/init/delete2.C
new file mode 100644 (file)
index 0000000..8a486be
--- /dev/null
@@ -0,0 +1,55 @@
+// PR c++/15097
+// { dg-do run }
+
+typedef __SIZE_TYPE__ size_t;
+
+extern "C" void * malloc (size_t);
+extern "C" void free (void *);
+extern "C" void abort(void);
+
+void *saved;
+
+void * operator new (size_t size)
+{
+  void *p = malloc (size);
+  saved = p;
+  return p;
+}
+
+void operator delete (void *p)
+{
+  if (p != saved)
+    abort ();
+  free (p);
+}
+
+struct B1
+{
+    virtual ~B1 () throw() {}
+    B1 (){}
+    int x;
+};
+struct B2
+{
+    virtual ~B2 () throw() {}
+    B2 (){}
+    int x;
+};
+struct D : B1, B2
+{
+    D (){}
+    ~D () throw() {}
+    int y;
+};
+void f1 (D*);
+void f2 (B2*);
+void f3 (B1*);
+int main (void)
+{
+    f1 (::new D);
+    f2 (::new D);     
+    f3 (::new D);
+}
+void f1 ( D* p) { ::delete p; }
+void f2 (B2* p) { ::delete p; }  
+void f3 (B1* p) { ::delete p; }