re PR c++/5757 (Throwing exception in constructor, causes segfault during unwind)
authorJason Merrill <jason@redhat.com>
Sun, 17 Mar 2002 13:54:04 +0000 (08:54 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 17 Mar 2002 13:54:04 +0000 (08:54 -0500)
        PR c++/5757
        * init.c (build_new_1): Pass the right pointer to op delete.

From-SVN: r50917

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/g++.dg/eh/new1.C [new file with mode: 0644]

index b5d947a2e666f774ac5aa533fe9de057a867aa80..9ef43ede9467e0ec70bcb1249e614261505af13b 100644 (file)
@@ -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
index 0e39646944a1cdf6d77b16b6e26545cb15e438bd..54954de566e6180888078930221d0030746478b4 100644 (file)
@@ -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 (file)
index 0000000..4c5c684
--- /dev/null
@@ -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;
+}