diff options
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/init.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/new1.C | 40 |
3 files changed, 56 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b5d947a2e66..9ef43ede946 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2002-03-17 Jason Merrill <jason@redhat.com> + + PR c++/5757 + * init.c (build_new_1): Pass the right pointer to op delete. + 2002-03-16 Nathan Sidwell <nathan@codesourcery.com> PR c++/4361 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 0e39646944a..54954de566e 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2288,7 +2288,7 @@ build_new_1 (exp) use_cookie = 0; /* When using placement new, users may not realize that they need the extra storage. We require that the operator called be - the global placement operator delete[]. */ + the global placement operator new[]. */ else if (placement && !TREE_CHAIN (placement) && same_type_p (TREE_TYPE (TREE_VALUE (placement)), ptr_type_node)) @@ -2473,13 +2473,22 @@ build_new_1 (exp) tree cleanup; int flags = (LOOKUP_NORMAL | (globally_qualified_p * LOOKUP_GLOBAL)); + tree delete_node; + + if (use_cookie) + /* Subtract the padding back out to get to the pointer returned + from operator new. */ + delete_node = fold (build (MINUS_EXPR, TREE_TYPE (alloc_node), + alloc_node, cookie_size)); + else + delete_node = alloc_node; /* The Standard is unclear here, but the right thing to do is to use the same method for finding deallocation functions that we use for finding allocation functions. */ flags |= LOOKUP_SPECULATIVELY; - cleanup = build_op_delete_call (dcode, alloc_node, size, flags, + cleanup = build_op_delete_call (dcode, delete_node, size, flags, (placement_allocation_fn_p ? alloc_call : NULL_TREE)); diff --git a/gcc/testsuite/g++.dg/eh/new1.C b/gcc/testsuite/g++.dg/eh/new1.C new file mode 100644 index 00000000000..4c5c684b5f2 --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/new1.C @@ -0,0 +1,40 @@ +// PR c++/5757 +// Test that when a constructor throws in a new-expression, we pass the +// right pointer to operator delete. + +// { dg-do run } + +#include <new> + +int ret = 1; + +void *ptr; +void * operator new[] (size_t s) throw (std::bad_alloc) +{ + ptr = operator new (s); + return ptr; +} + +void operator delete[] (void *p) throw () +{ + if (p == ptr) + ret = 0; + operator delete (p); +} + +struct A +{ + A() { throw 1; } + ~A() {} +}; + +int +main () +{ + try + { + A *p = new A[4]; + } + catch (...) {} + return ret; +} |