From: jason Date: Thu, 6 Sep 2007 01:24:59 +0000 (+0000) Subject: PR c++/15097 X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;h=56a58a8c060348988af2dbabebfed25c02de5e32;p=pf3gnuchains%2Fgcc-fork.git 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@128172 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b8fb9711721..a32ecdb1560 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2007-09-05 Jason Merrill + + 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 * decl.c (duplicate_decls): Set TREE_NOTHROW on __builtin_XX @@ -28,6 +36,9 @@ 2007-09-04 Jason Merrill + * 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 71f401f247c..9bd8ed2c302 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b46d687a903..1aa732c26b0 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 8253a283d69..9d2ffdf2823 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -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 index 00000000000..8a486beaa5a --- /dev/null +++ b/gcc/testsuite/g++.dg/init/delete2.C @@ -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; }