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/decl2.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/decl2.c')
-rw-r--r-- | gcc/cp/decl2.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a163558..13c156b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1739,10 +1739,11 @@ coerce_new_type (tree type, location_t loc) return type; } -tree -coerce_delete_type (tree type, location_t loc) +void +coerce_delete_type (tree decl, location_t loc) { int e = 0; + tree type = TREE_TYPE (decl); tree args = TYPE_ARG_TYPES (type); gcc_assert (TREE_CODE (type) == FUNCTION_TYPE); @@ -1754,19 +1755,38 @@ coerce_delete_type (tree type, location_t loc) void_type_node); } + tree ptrtype = ptr_type_node; + if (destroying_delete_p (decl)) + { + if (DECL_CLASS_SCOPE_P (decl)) + /* If the function is a destroying operator delete declared in class type + C, the type of its first parameter shall be C*. */ + ptrtype = TYPE_POINTER_TO (DECL_CONTEXT (decl)); + else + /* A destroying operator delete shall be a class member function named + operator delete. */ + error_at (loc, "destroying operator delete must be a member function"); + const ovl_op_info_t *op = IDENTIFIER_OVL_OP_INFO (DECL_NAME (decl)); + if (op->flags & OVL_OP_FLAG_VEC) + error_at (loc, "operator delete[] cannot be a destroying delete"); + if (!usual_deallocation_fn_p (decl)) + error_at (loc, "destroying operator delete must be a usual " + "deallocation function"); + } + if (!args || args == void_list_node - || !same_type_p (TREE_VALUE (args), ptr_type_node)) + || !same_type_p (TREE_VALUE (args), ptrtype)) { e = 2; if (args && args != void_list_node) args = TREE_CHAIN (args); error_at (loc, "%<operator delete%> takes type %qT as first parameter", - ptr_type_node); + ptrtype); } switch (e) { case 2: - args = tree_cons (NULL_TREE, ptr_type_node, args); + args = tree_cons (NULL_TREE, ptrtype, args); /* Fall through. */ case 1: type = (cxx_copy_lang_qualifiers @@ -1776,7 +1796,7 @@ coerce_delete_type (tree type, location_t loc) default:; } - return type; + TREE_TYPE (decl) = type; } /* DECL is a VAR_DECL for a vtable: walk through the entries in the vtable |