aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2001-05-22 00:31:36 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2001-05-22 00:31:36 +0000
commit3f41ffd8c39bedd88fbf0f7fcc42559397d69103 (patch)
tree3d7688183b2a2137423e2873a5b2ff048d8d847a /gcc
parentb1e6ab035edd172c58ef3acb91a9b955921d13f0 (diff)
downloadgcc-3f41ffd8c39bedd88fbf0f7fcc42559397d69103.zip
gcc-3f41ffd8c39bedd88fbf0f7fcc42559397d69103.tar.gz
gcc-3f41ffd8c39bedd88fbf0f7fcc42559397d69103.tar.bz2
call.c (build_op_delete_call): Ignore exception-specifications when looking for matching delete operators.
* call.c (build_op_delete_call): Ignore exception-specifications when looking for matching delete operators. * init.c (build_new_1): Compute whether or not the allocation function used is a placement allocation function or not, and communicate this information to build_op_delete_call. From-SVN: r42413
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c55
-rw-r--r--gcc/cp/init.c27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/new7.C39
4 files changed, 112 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index eda85ec..5d6ca8f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2001-05-21 Mark Mitchell <mark@codesourcery.com>
+
+ * call.c (build_op_delete_call): Ignore exception-specifications
+ when looking for matching delete operators.
+ * init.c (build_new_1): Compute whether or not the allocation
+ function used is a placement allocation function or not, and
+ communicate this information to build_op_delete_call.
+
2001-05-21 Jason Merrill <jason_merrill@redhat.com>
* class.c (build_vtable_entry_ref): Lose vtbl parm. Fix for new abi.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6694f56..5367cc5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3545,7 +3545,7 @@ builtin:
used to determine what the corresponding new looked like.
SIZE is the size of the memory block to be deleted.
FLAGS are the usual overloading flags.
- PLACEMENT is the corresponding placement new call, or 0. */
+ PLACEMENT is the corresponding placement new call, or NULL_TREE. */
tree
build_op_delete_call (code, addr, size, flags, placement)
@@ -3620,23 +3620,50 @@ build_op_delete_call (code, addr, size, flags, placement)
argtypes = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, sizetype,
void_list_node));
-
fntype = build_function_type (void_type_node, argtypes);
- fn = instantiate_type (fntype, fns, itf_no_attributes);
- if (fn != error_mark_node)
+ /* Go through the `operator delete' functions looking for one
+ with a matching type. */
+ for (fn = BASELINK_P (fns) ? TREE_VALUE (fns) : fns;
+ fn;
+ fn = OVL_NEXT (fn))
{
- /* Member functions. */
- if (BASELINK_P (fns))
- enforce_access (type, fn);
-
- if (pass == 0)
- args = tree_cons (NULL_TREE, addr, args);
- else
- args = tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, size));
- return build_function_call (fn, args);
+ tree t;
+
+ /* Exception specifications on the `delete' operator do not
+ matter. */
+ t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
+ NULL_TREE);
+ /* We also don't compare attributes. We're really just
+ trying to check the types of the first two parameters. */
+ if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
+ break;
}
+
+ /* If we found a match, we're done. */
+ if (fn)
+ break;
+ }
+
+ /* If we have a matching function, call it. */
+ if (fn)
+ {
+ /* Make sure we have the actual function, and not an
+ OVERLOAD. */
+ fn = OVL_CURRENT (fn);
+
+ /* If the FN is a member function, make sure that it is
+ accessible. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ enforce_access (type, fn);
+
+ if (pass == 0)
+ args = tree_cons (NULL_TREE, addr, args);
+ else
+ args = tree_cons (NULL_TREE, addr,
+ build_tree_list (NULL_TREE, size));
+
+ return build_function_call (fn, args);
}
/* If we are doing placement delete we do nothing if we don't find a
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1ac6f73..6bce193 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2293,6 +2293,9 @@ build_new_1 (exp)
beginning of the storage allocated for an array-new expression in
order to store the number of elements. */
tree cookie_size = NULL_TREE;
+ /* True if the function we are calling is a placement allocation
+ function. */
+ bool placement_allocation_fn_p;
placement = TREE_OPERAND (exp, 0);
type = TREE_OPERAND (exp, 1);
@@ -2418,8 +2421,25 @@ build_new_1 (exp)
if (alloc_call == error_mark_node)
return error_mark_node;
- if (alloc_call == NULL_TREE)
- abort ();
+ /* The ALLOC_CALL should be a CALL_EXPR, and the first operand
+ should be the address of a known FUNCTION_DECL. */
+ my_friendly_assert (TREE_CODE (alloc_call) == CALL_EXPR, 20000521);
+ t = TREE_OPERAND (alloc_call, 0);
+ my_friendly_assert (TREE_CODE (t) == ADDR_EXPR, 20000521);
+ t = TREE_OPERAND (t, 0);
+ my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 20000521);
+ /* Now, check to see if this function is actually a placement
+ allocation function. This can happen even when PLACEMENT is NULL
+ because we might have something like:
+
+ struct S { void* operator new (size_t, int i = 0); };
+
+ A call to `new S' will get this allocation function, even though
+ there is no explicit placement argument. If there is more than
+ one argument, or there are variable arguments, then this is a
+ placement allocation function. */
+ placement_allocation_fn_p
+ = (type_num_arguments (TREE_TYPE (t)) > 1 || varargs_function_p (t));
/* unless an allocation function is declared with an empty excep-
tion-specification (_except.spec_), throw(), it indicates failure to
@@ -2536,7 +2556,8 @@ build_new_1 (exp)
flags |= LOOKUP_SPECULATIVELY;
cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
- alloc_call);
+ (placement_allocation_fn_p
+ ? alloc_call : NULL_TREE));
/* Ack! First we allocate the memory. Then we set our sentry
variable to true, and expand a cleanup that deletes the memory
diff --git a/gcc/testsuite/g++.old-deja/g++.other/new7.C b/gcc/testsuite/g++.old-deja/g++.other/new7.C
new file mode 100644
index 0000000..35ec0bb
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/new7.C
@@ -0,0 +1,39 @@
+// Origin: philip_martin@ntlworld.com
+
+#include <new>
+
+extern "C" void abort();
+
+bool new_flag = false;
+bool delete_flag = false;
+
+struct X {
+ X()
+ {
+ throw 1;
+ }
+ void* operator new ( std::size_t n ) throw ( std::bad_alloc )
+ {
+ new_flag = true;
+ return ::operator new( n );
+ }
+ void operator delete( void* p, std::size_t n ) throw()
+ {
+ delete_flag = true;
+ ::operator delete( p );
+ }
+};
+
+int
+main()
+{
+ try
+ {
+ X* x = new X; // gcc 3.0 fails to call operator delete when X::X throws
+ }
+ catch ( ... )
+ {
+ }
+ if ( ! new_flag || ! delete_flag )
+ ::abort();
+}