mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-21 14:49:41 +08:00
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:
parent
b1e6ab035e
commit
3f41ffd8c3
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
39
gcc/testsuite/g++.old-deja/g++.other/new7.C
Normal file
39
gcc/testsuite/g++.old-deja/g++.other/new7.C
Normal 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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user