Commit f7f36e3d by Jason Merrill Committed by Jason Merrill

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
parent 7f16ac89
2019-05-06 Jason Merrill <jason@redhat.com>
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 <jason@redhat.com>
PR c++/86485 - -Wmaybe-unused with empty class ?:
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment