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
This commit is contained in:
Mark Mitchell 2001-05-22 00:31:36 +00:00 committed by Mark Mitchell
parent b1e6ab035e
commit 3f41ffd8c3
4 changed files with 111 additions and 16 deletions

View File

@ -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.

View File

@ -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);
tree t;
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);
/* 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

View File

@ -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

View File

@ -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();
}