From f7f36e3dc102d8ffb776f31abb48c33b1b830ebe Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 7 May 2019 18:37:24 -0400 Subject: [PATCH] PR c++/90171 - reorganize usual_deallocation_fn_p When fixing 90171 it struck me as undesirable to have so many separate functions that all needed to know about the definition of a usual deallocation function. So this patch condenses them into one. I left destroying_delete_p because it is used by other files as well. * call.c (struct dealloc_info): New. (usual_deallocation_fn_p): Take a dealloc_info*. (aligned_deallocation_fn_p, sized_deallocation_fn_p): Remove. (build_op_delete_call): Adjust. From-SVN: r270986 --- gcc/cp/ChangeLog | 8 +++ gcc/cp/call.c | 144 ++++++++++++++++++++--------------------------- 2 files changed, 70 insertions(+), 82 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d90cc099767..dade3e0c8b9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-05-06 Jason Merrill + + PR c++/90171 - reorganize usual_deallocation_fn_p + * call.c (struct dealloc_info): New. + (usual_deallocation_fn_p): Take a dealloc_info*. + (aligned_deallocation_fn_p, sized_deallocation_fn_p): Remove. + (build_op_delete_call): Adjust. + 2019-05-07 Jason Merrill PR c++/86485 - -Wmaybe-unused with empty class ?: diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1a79017eff4..20db2974b56 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6348,63 +6348,22 @@ destroying_delete_p (tree t) return std_destroying_delete_t_p (type) ? type : NULL_TREE; } -/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation - function (3.7.4.2 [basic.stc.dynamic.deallocation]) with a parameter of - std::align_val_t. */ - -static bool -aligned_deallocation_fn_p (tree t) +struct dealloc_info { - if (!aligned_new_threshold) - return false; - - /* A template instance is never a usual deallocation function, - regardless of its signature. */ - if (TREE_CODE (t) == TEMPLATE_DECL - || primary_template_specialization_p (t)) - return false; - - tree a = FUNCTION_ARG_CHAIN (t); - if (destroying_delete_p (t)) - a = TREE_CHAIN (a); - if (same_type_p (TREE_VALUE (a), align_type_node) - && TREE_CHAIN (a) == void_list_node) - return true; - if (!same_type_p (TREE_VALUE (a), size_type_node)) - return false; - a = TREE_CHAIN (a); - if (a && same_type_p (TREE_VALUE (a), align_type_node) - && TREE_CHAIN (a) == void_list_node) - return true; - return false; -} + bool sized; + bool aligned; + tree destroying; +}; -/* Returns true if FN is a usual deallocation fn with a size_t parameter. */ +/* Returns true iff T, an element of an OVERLOAD chain, is a usual deallocation + function (3.7.4.2 [basic.stc.dynamic.deallocation]). If so, and DI is + non-null, also set *DI. */ static bool -sized_deallocation_fn_p (tree fn) +usual_deallocation_fn_p (tree t, dealloc_info *di) { - tree t = FUNCTION_ARG_CHAIN (fn); - if (destroying_delete_p (fn)) - t = TREE_CHAIN (t); - if (!t || !same_type_p (TREE_VALUE (t), size_type_node)) - return false; - t = TREE_CHAIN (t); - if (t == void_list_node) - return true; - if (aligned_new_threshold && t - && same_type_p (TREE_VALUE (t), align_type_node) - && TREE_CHAIN (t) == void_list_node) - return true; - return false; -} + if (di) *di = dealloc_info(); -/* Returns true iff T, an element of an OVERLOAD chain, is a usual - deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */ - -bool -usual_deallocation_fn_p (tree t) -{ /* A template instance is never a usual deallocation function, regardless of its signature. */ if (TREE_CODE (t) == TEMPLATE_DECL @@ -6418,17 +6377,33 @@ usual_deallocation_fn_p (tree t) - optionally, a parameter of type std::align_val_t. */ bool global = DECL_NAMESPACE_SCOPE_P (t); tree chain = FUNCTION_ARG_CHAIN (t); - if (!chain) - return false; - if (destroying_delete_p (t)) - chain = TREE_CHAIN (chain); - if (chain == void_list_node - || ((!global || flag_sized_deallocation) - && sized_deallocation_fn_p (t))) - return true; - if (aligned_deallocation_fn_p (t)) - return true; - return false; + if (chain && destroying_delete_p (t)) + { + if (di) di->destroying = TREE_VALUE (chain); + chain = TREE_CHAIN (chain); + } + if (chain + && (!global || flag_sized_deallocation) + && same_type_p (TREE_VALUE (chain), size_type_node)) + { + if (di) di->sized = true; + chain = TREE_CHAIN (chain); + } + if (chain && aligned_new_threshold + && same_type_p (TREE_VALUE (chain), align_type_node)) + { + if (di) di->aligned = true; + chain = TREE_CHAIN (chain); + } + return (chain == void_list_node); +} + +/* Just return whether FN is a usual deallocation function. */ + +bool +usual_deallocation_fn_p (tree fn) +{ + return usual_deallocation_fn_p (fn, NULL); } /* Build a call to operator delete. This has to be handled very specially, @@ -6457,6 +6432,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, { tree fn = NULL_TREE; tree fns, fnname, type, t; + dealloc_info di_fn = { }; if (addr == error_mark_node) return error_mark_node; @@ -6575,11 +6551,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, for (lkp_iterator iter (MAYBE_BASELINK_FUNCTIONS (fns)); iter; ++iter) { tree elt = *iter; - if (usual_deallocation_fn_p (elt)) + dealloc_info di_elt; + if (usual_deallocation_fn_p (elt, &di_elt)) { if (!fn) { fn = elt; + di_fn = di_elt; continue; } @@ -6587,12 +6565,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, operator delete, all deallocation functions that are not destroying operator deletes are eliminated from further consideration. */ - bool fn_destroying = destroying_delete_p (fn); - bool elt_destroying = destroying_delete_p (elt); - if (elt_destroying != fn_destroying) + if (di_elt.destroying != di_fn.destroying) { - if (elt_destroying) - fn = elt; + if (di_elt.destroying) + { + fn = elt; + di_fn = di_elt; + } continue; } @@ -6606,13 +6585,13 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, if (aligned_new_threshold) { bool want_align = type_has_new_extended_alignment (type); - bool fn_align = aligned_deallocation_fn_p (fn); - bool elt_align = aligned_deallocation_fn_p (elt); - - if (elt_align != fn_align) + if (di_elt.aligned != di_fn.aligned) { - if (want_align == elt_align) - fn = elt; + if (want_align == di_elt.aligned) + { + fn = elt; + di_fn = di_elt; + } continue; } } @@ -6639,11 +6618,12 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, /* We need a cookie to determine the array size. */ want_size = false; } - bool fn_size = sized_deallocation_fn_p (fn); - bool elt_size = sized_deallocation_fn_p (elt); - gcc_assert (fn_size != elt_size); - if (want_size == elt_size) - fn = elt; + gcc_assert (di_fn.sized != di_elt.sized); + if (want_size == di_elt.sized) + { + fn = elt; + di_fn = di_elt; + } } } @@ -6678,7 +6658,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, } else { - tree destroying = destroying_delete_p (fn); + tree destroying = di_fn.destroying; if (destroying) { /* Strip const and volatile from addr but retain the type of the @@ -6696,9 +6676,9 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, args->quick_push (addr); if (destroying) args->quick_push (destroying); - if (sized_deallocation_fn_p (fn)) + if (di_fn.sized) args->quick_push (size); - if (aligned_deallocation_fn_p (fn)) + if (di_fn.aligned) { tree al = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (type)); args->quick_push (al); -- 2.30.2