diff options
author | Jason Merrill <jason@redhat.com> | 2002-03-17 08:54:04 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2002-03-17 08:54:04 -0500 |
commit | beb9c8a2348bfc9095cf35684aee67cdfd7461ef (patch) | |
tree | 78dc03e4496bc87949dbea571f48eadc38004b20 | |
parent | 0ac7f9233809d56331d54ba42e611722ee2aa71e (diff) | |
download | gcc-beb9c8a2348bfc9095cf35684aee67cdfd7461ef.zip gcc-beb9c8a2348bfc9095cf35684aee67cdfd7461ef.tar.gz gcc-beb9c8a2348bfc9095cf35684aee67cdfd7461ef.tar.bz2 |
re PR c++/5757 (Throwing exception in constructor, causes segfault during unwind)
PR c++/5757
* init.c (build_new_1): Pass the right pointer to op delete.
From-SVN: r50917
-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 b5d947a..9ef43ed 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 0e39646..54954de 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 0000000..4c5c684 --- /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; +} |