diff options
author | Jason Merrill <jason@redhat.com> | 2018-11-12 23:40:01 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2018-11-12 23:40:01 -0500 |
commit | a6bb6b07f76c4431cb5a2a520ac33f7c970b80c1 (patch) | |
tree | 4da8d10f970dd37ab850c548d36cd4980e9a623d /gcc/cp/optimize.c | |
parent | 7de37c97b4031ba61c867cf6fadf63916c666894 (diff) | |
download | gcc-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.c | 27 |
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); |