aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/optimize.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-11-12 23:40:01 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-11-12 23:40:01 -0500
commita6bb6b07f76c4431cb5a2a520ac33f7c970b80c1 (patch)
tree4da8d10f970dd37ab850c548d36cd4980e9a623d /gcc/cp/optimize.c
parent7de37c97b4031ba61c867cf6fadf63916c666894 (diff)
downloadgcc-a6bb6b07f76c4431cb5a2a520ac33f7c970b80c1.zip
gcc-a6bb6b07f76c4431cb5a2a520ac33f7c970b80c1.tar.gz
gcc-a6bb6b07f76c4431cb5a2a520ac33f7c970b80c1.tar.bz2
Implement P0722R3, destroying operator delete.
A destroying operator delete takes responsibility for calling the destructor for the object it is deleting; this is intended to be useful for sized delete of a class allocated with a trailing buffer, where the compiler can't know the size of the allocation, and so would pass the wrong size to the non-destroying sized operator delete. gcc/c-family/ * c-cppbuiltin.c (c_cpp_builtins): Define __cpp_impl_destroying_delete. gcc/cp/ * call.c (std_destroying_delete_t_p, destroying_delete_p): New. (aligned_deallocation_fn_p, usual_deallocation_fn_p): Use destroying_delete_p. (build_op_delete_call): Handle destroying delete. * decl2.c (coerce_delete_type): Handle destroying delete. * init.c (build_delete): Don't call dtor with destroying delete. * optimize.c (build_delete_destructor_body): Likewise. libstdc++-v3/ * libsupc++/new (std::destroying_delete_t): New. From-SVN: r266053
Diffstat (limited to 'gcc/cp/optimize.c')
-rw-r--r--gcc/cp/optimize.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 3923a5f..da068b5 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -117,11 +117,6 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
tree parm = DECL_ARGUMENTS (delete_dtor);
tree virtual_size = cxx_sizeof (current_class_type);
- /* Call the corresponding complete destructor. */
- gcc_assert (complete_dtor);
- tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
- tf_warning_or_error);
-
/* Call the delete function. */
tree call_delete = build_op_delete_call (DELETE_EXPR, current_class_ptr,
virtual_size,
@@ -130,10 +125,26 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
/*alloc_fn=*/NULL_TREE,
tf_warning_or_error);
- /* Operator delete must be called, whether or not the dtor throws. */
- add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node, call_dtor, call_delete));
+ tree op = get_callee_fndecl (call_delete);
+ if (op && DECL_P (op) && destroying_delete_p (op))
+ {
+ /* The destroying delete will handle calling complete_dtor. */
+ add_stmt (call_delete);
+ }
+ else
+ {
+ /* Call the corresponding complete destructor. */
+ gcc_assert (complete_dtor);
+ tree call_dtor = build_cxx_call (complete_dtor, 1, &parm,
+ tf_warning_or_error);
+
+ /* Operator delete must be called, whether or not the dtor throws. */
+ add_stmt (build2 (TRY_FINALLY_EXPR, void_type_node,
+ call_dtor, call_delete));
+ }
- /* Return the address of the object. */
+ /* Return the address of the object.
+ ??? How is it useful to return an invalid address? */
if (targetm.cxx.cdtor_returns_this ())
{
tree val = DECL_ARGUMENTS (delete_dtor);