Commit d395d8e7 by Jason Merrill Committed by Jason Merrill

PR c++/90171 - ICE with destroying delete with size_t parm.

The problem here was that "second parm is size_t" is false for a destroying
sized delete.  So let's introduce sized_deallocation_fn_p when that's what
we're asking, and reserve second_parm_is_size_t for the specific case of
warning about possible confusion with placement delete.

	* call.c (sized_deallocation_fn_p): New.  Use it instead of
	second_parm_is_size_t in most cases.
	(second_parm_is_size_t): Don't check for aligned.

From-SVN: r270467
parent f9eff98e
2019-04-19 Jason Merrill <jason@redhat.com>
PR c++/90171 - ICE with destroying delete with size_t parm.
* call.c (sized_deallocation_fn_p): New. Use it instead of
second_parm_is_size_t in most cases.
(second_parm_is_size_t): Don't check for aligned.
2019-04-19 Paolo Carlini <paolo.carlini@oracle.com> 2019-04-19 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/89900 PR c++/89900
......
...@@ -6307,10 +6307,6 @@ second_parm_is_size_t (tree fn) ...@@ -6307,10 +6307,6 @@ second_parm_is_size_t (tree fn)
t = TREE_CHAIN (t); t = TREE_CHAIN (t);
if (t == void_list_node) if (t == void_list_node)
return true; 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; return false;
} }
...@@ -6383,6 +6379,26 @@ aligned_deallocation_fn_p (tree t) ...@@ -6383,6 +6379,26 @@ aligned_deallocation_fn_p (tree t)
return false; return false;
} }
/* Returns true if FN is a usual deallocation fn with a size_t parameter. */
static bool
sized_deallocation_fn_p (tree fn)
{
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;
}
/* Returns true iff T, an element of an OVERLOAD chain, is a usual /* Returns true iff T, an element of an OVERLOAD chain, is a usual
deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */ deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */
...@@ -6395,13 +6411,11 @@ usual_deallocation_fn_p (tree t) ...@@ -6395,13 +6411,11 @@ usual_deallocation_fn_p (tree t)
|| primary_template_specialization_p (t)) || primary_template_specialization_p (t))
return false; return false;
/* If a class T has a member deallocation function named operator delete /* A usual deallocation function is a deallocation function whose parameters
with exactly one parameter, then that function is a usual after the first are
(non-placement) deallocation function. If class T does not declare - optionally, a parameter of type std::destroying_delete_t, then
such an operator delete but does declare a member deallocation - optionally, a parameter of type std::size_t, then
function named operator delete with exactly two parameters, the second - optionally, a parameter of type std::align_val_t. */
of which has type std::size_t (18.2), then this function is a usual
deallocation function. */
bool global = DECL_NAMESPACE_SCOPE_P (t); bool global = DECL_NAMESPACE_SCOPE_P (t);
tree chain = FUNCTION_ARG_CHAIN (t); tree chain = FUNCTION_ARG_CHAIN (t);
if (!chain) if (!chain)
...@@ -6410,7 +6424,7 @@ usual_deallocation_fn_p (tree t) ...@@ -6410,7 +6424,7 @@ usual_deallocation_fn_p (tree t)
chain = TREE_CHAIN (chain); chain = TREE_CHAIN (chain);
if (chain == void_list_node if (chain == void_list_node
|| ((!global || flag_sized_deallocation) || ((!global || flag_sized_deallocation)
&& second_parm_is_size_t (t))) && sized_deallocation_fn_p (t)))
return true; return true;
if (aligned_deallocation_fn_p (t)) if (aligned_deallocation_fn_p (t))
return true; return true;
...@@ -6625,8 +6639,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, ...@@ -6625,8 +6639,8 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
/* We need a cookie to determine the array size. */ /* We need a cookie to determine the array size. */
want_size = false; want_size = false;
} }
bool fn_size = second_parm_is_size_t (fn); bool fn_size = sized_deallocation_fn_p (fn);
bool elt_size = second_parm_is_size_t (elt); bool elt_size = sized_deallocation_fn_p (elt);
gcc_assert (fn_size != elt_size); gcc_assert (fn_size != elt_size);
if (want_size == elt_size) if (want_size == elt_size)
fn = elt; fn = elt;
...@@ -6682,7 +6696,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, ...@@ -6682,7 +6696,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
args->quick_push (addr); args->quick_push (addr);
if (destroying) if (destroying)
args->quick_push (destroying); args->quick_push (destroying);
if (second_parm_is_size_t (fn)) if (sized_deallocation_fn_p (fn))
args->quick_push (size); args->quick_push (size);
if (aligned_deallocation_fn_p (fn)) if (aligned_deallocation_fn_p (fn))
{ {
......
// PR c++/90171
// { dg-do compile { target c++2a } }
#include <new>
struct A {
void operator delete(A*, std::destroying_delete_t, std::align_val_t);
void operator delete(A*, std::destroying_delete_t, std::size_t, std::align_val_t);
};
void delete_A(A *a) { delete a; }
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