aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2002-03-17 08:54:04 -0500
committerJason Merrill <jason@gcc.gnu.org>2002-03-17 08:54:04 -0500
commitbeb9c8a2348bfc9095cf35684aee67cdfd7461ef (patch)
tree78dc03e4496bc87949dbea571f48eadc38004b20
parent0ac7f9233809d56331d54ba42e611722ee2aa71e (diff)
downloadgcc-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/ChangeLog5
-rw-r--r--gcc/cp/init.c13
-rw-r--r--gcc/testsuite/g++.dg/eh/new1.C40
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;
+}