Commit 52682a1b by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (CLASSTYPE_DESTRUCTORS): Fix typo in comment.

	* cp-tree.h (CLASSTYPE_DESTRUCTORS): Fix typo in comment.
	* call.c (build_op_delete_call): Simplify to remove duplicate
	code.
	* class.c (clone_function_decl): Don't build the deleting variant
	of a non-virtual destructor.
	* decl.c (finish_destructor_body): Don't call delete if this is a
	non-virtual destructor.
	* init.c (build_delete): Explicitly call `operator delete' when
	deleting an object with a non-virtual destructor.

From-SVN: r39659
parent 97a4d32e
2001-02-13 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (CLASSTYPE_DESTRUCTORS): Fix typo in comment.
* call.c (build_op_delete_call): Simplify to remove duplicate
code.
* class.c (clone_function_decl): Don't build the deleting variant
of a non-virtual destructor.
* decl.c (finish_destructor_body): Don't call delete if this is a
non-virtual destructor.
* init.c (build_delete): Explicitly call `operator delete' when
deleting an object with a non-virtual destructor.
2001-02-13 Jason Merrill <jason@redhat.com> 2001-02-13 Jason Merrill <jason@redhat.com>
* lang-specs.h: Add more __EXCEPTIONS. * lang-specs.h: Add more __EXCEPTIONS.
......
...@@ -3547,6 +3547,7 @@ build_op_delete_call (code, addr, size, flags, placement) ...@@ -3547,6 +3547,7 @@ build_op_delete_call (code, addr, size, flags, placement)
int flags; int flags;
{ {
tree fn, fns, fnname, fntype, argtypes, args, type; tree fn, fns, fnname, fntype, argtypes, args, type;
int pass;
if (addr == error_mark_node) if (addr == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -3595,48 +3596,45 @@ build_op_delete_call (code, addr, size, flags, placement) ...@@ -3595,48 +3596,45 @@ build_op_delete_call (code, addr, size, flags, placement)
args = NULL_TREE; args = NULL_TREE;
} }
argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
fntype = build_function_type (void_type_node, argtypes);
/* Strip const and volatile from addr. */ /* Strip const and volatile from addr. */
addr = cp_convert (ptr_type_node, addr); addr = cp_convert (ptr_type_node, addr);
fn = instantiate_type (fntype, fns, itf_no_attributes); /* We make two tries at finding a matching `operator delete'. On
the first pass, we look for an one-operator (or placement)
if (fn != error_mark_node) operator delete. If we're not doing placement delete, then on
the second pass we look for a two-argument delete. */
for (pass = 0; pass < (placement ? 1 : 2); ++pass)
{ {
if (TREE_CODE (fns) == TREE_LIST) if (pass == 0)
/* Member functions. */ argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
enforce_access (type, fn); else
return build_function_call (fn, tree_cons (NULL_TREE, addr, args)); /* Normal delete; now try to find a match including the size
} argument. */
/* If we are doing placement delete we do nothing if we don't find a
matching op delete. */
if (placement)
return NULL_TREE;
/* Normal delete; now try to find a match including the size argument. */
argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes = tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, sizetype, void_list_node)); tree_cons (NULL_TREE, sizetype,
fntype = build_function_type (void_type_node, argtypes); void_list_node));
fntype = build_function_type (void_type_node, argtypes);
fn = instantiate_type (fntype, fns, itf_no_attributes); fn = instantiate_type (fntype, fns, itf_no_attributes);
if (fn != error_mark_node) if (fn != error_mark_node)
{ {
if (BASELINK_P (fns))
/* Member functions. */ /* Member functions. */
if (BASELINK_P (fns))
enforce_access (type, fn); enforce_access (type, fn);
return build_function_call
(fn, tree_cons (NULL_TREE, addr, if (pass == 0)
build_tree_list (NULL_TREE, size))); 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);
}
} }
/* finish_function passes LOOKUP_SPECULATIVELY if we're in a /* If we are doing placement delete we do nothing if we don't find a
destructor, in which case the error should be deferred matching op delete. */
until someone actually tries to delete one of these. */ if (placement)
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE; return NULL_TREE;
cp_error ("no suitable `operator delete' for `%T'", type); cp_error ("no suitable `operator delete' for `%T'", type);
......
...@@ -4319,10 +4319,16 @@ clone_function_decl (fn, update_method_vec_p) ...@@ -4319,10 +4319,16 @@ clone_function_decl (fn, update_method_vec_p)
version. We clone the deleting version first because that version. We clone the deleting version first because that
means it will go second on the TYPE_METHODS list -- and that means it will go second on the TYPE_METHODS list -- and that
corresponds to the correct layout order in the virtual corresponds to the correct layout order in the virtual
function table. */ function table.
For a non-virtual destructor, we do not build a deleting
destructor. */
if (DECL_VIRTUAL_P (fn))
{
clone = build_clone (fn, deleting_dtor_identifier); clone = build_clone (fn, deleting_dtor_identifier);
if (update_method_vec_p) if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
}
clone = build_clone (fn, complete_dtor_identifier); clone = build_clone (fn, complete_dtor_identifier);
if (update_method_vec_p) if (update_method_vec_p)
add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0); add_method (DECL_CONTEXT (clone), clone, /*error_p=*/0);
......
...@@ -1456,7 +1456,7 @@ struct lang_type ...@@ -1456,7 +1456,7 @@ struct lang_type
#define CLASSTYPE_CONSTRUCTORS(NODE) \ #define CLASSTYPE_CONSTRUCTORS(NODE) \
(TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT)) (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_CONSTRUCTOR_SLOT))
/* A FUNCTION_DECL for the destructor for NODE. These are te /* A FUNCTION_DECL for the destructor for NODE. These are the
destructors that take an in-charge parameter. */ destructors that take an in-charge parameter. */
#define CLASSTYPE_DESTRUCTORS(NODE) \ #define CLASSTYPE_DESTRUCTORS(NODE) \
(TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT)) (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (NODE), CLASSTYPE_DESTRUCTOR_SLOT))
......
...@@ -13730,9 +13730,7 @@ static void ...@@ -13730,9 +13730,7 @@ static void
finish_destructor_body () finish_destructor_body ()
{ {
tree compound_stmt; tree compound_stmt;
tree virtual_size;
tree exprstmt; tree exprstmt;
tree if_stmt;
/* Create a block to contain all the extra code. */ /* Create a block to contain all the extra code. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
...@@ -13814,19 +13812,18 @@ finish_destructor_body () ...@@ -13814,19 +13812,18 @@ finish_destructor_body ()
} }
} }
virtual_size = c_sizeof (current_class_type); /* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl))
/* At the end, call delete if that's what's requested. */ {
tree if_stmt;
tree virtual_size = c_sizeof (current_class_type);
/* FDIS sez: At the point of definition of a virtual destructor /* [class.dtor]
(including an implicit definition), non-placement operator delete
shall be looked up in the scope of the destructor's class and if
found shall be accessible and unambiguous.
This is somewhat unclear, but I take it to mean that if the class At the point of definition of a virtual destructor (including
only defines placement deletes we don't do anything here. So we an implicit definition), non-placement operator delete shall
pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if be looked up in the scope of the destructor's class and if
they ever try to delete one of these. */ found shall be accessible and unambiguous. */
exprstmt = build_op_delete_call exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size, (DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE); LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
...@@ -13839,6 +13836,7 @@ finish_destructor_body () ...@@ -13839,6 +13836,7 @@ finish_destructor_body ()
finish_expr_stmt (exprstmt); finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt); finish_then_clause (if_stmt);
finish_if_stmt (); finish_if_stmt ();
}
/* Close the block we started above. */ /* Close the block we started above. */
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
......
...@@ -3235,6 +3235,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3235,6 +3235,9 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
tree do_delete = NULL_TREE; tree do_delete = NULL_TREE;
tree ifexp; tree ifexp;
/* For `::delete x', we must not use the deleting destructor
since then we would not be sure to get the global `operator
delete'. */
if (use_global_delete && auto_delete == sfk_deleting_destructor) if (use_global_delete && auto_delete == sfk_deleting_destructor)
{ {
/* Delete the object. */ /* Delete the object. */
...@@ -3243,6 +3246,21 @@ build_delete (type, addr, auto_delete, flags, use_global_delete) ...@@ -3243,6 +3246,21 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
call. */ call. */
auto_delete = sfk_complete_destructor; auto_delete = sfk_complete_destructor;
} }
/* If the destructor is non-virtual, there is no deleting
variant. Instead, we must explicitly call the appropriate
`operator delete' here. */
else if (!DECL_VIRTUAL_P (CLASSTYPE_DESTRUCTORS (type))
&& auto_delete == sfk_deleting_destructor)
{
/* Buidl the call. */
do_delete = build_op_delete_call (DELETE_EXPR,
addr,
c_sizeof_nowarn (type),
LOOKUP_NORMAL,
NULL_TREE);
/* Call the complete object destructor. */
auto_delete = sfk_complete_destructor;
}
expr = build_dtor_call (ref, auto_delete, flags); expr = build_dtor_call (ref, auto_delete, flags);
if (do_delete) if (do_delete)
......
// Build don't link: // Build don't link:
// Copyright (C) 1999 Free Software Foundation // Copyright (C) 1999, 2001 Free Software Foundation
// by Alexandre Oliva <oliva@dcc.unicamp.br> // by Alexandre Oliva <oliva@dcc.unicamp.br>
// simplified from bug report by K. Haley <khaley@bigfoot.com> // simplified from bug report by K. Haley <khaley@bigfoot.com>
...@@ -21,7 +21,7 @@ struct bar : foo { ...@@ -21,7 +21,7 @@ struct bar : foo {
delete this; // ERROR - delete is private delete this; // ERROR - delete is private
// An implicit invocation of delete is emitted in destructors, but // An implicit invocation of delete is emitted in destructors, but
// it should only be checked in virtual destructors // it should only be checked in virtual destructors
} // gets bogus error - not virtual - XFAIL *-*-* } // gets bogus error - not virtual
} bar_; } bar_;
struct baz : foo { struct baz : foo {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment