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
- 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,
{
tree fn = NULL_TREE;
tree fns, fnname, type, t;
+ dealloc_info di_fn = { };
if (addr == error_mark_node)
return error_mark_node;
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;
}
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;
}
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;
}
}
/* 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;
+ }
}
}
}
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
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);