@@ -6307,10 +6307,6 @@ second_parm_is_size_t (tree fn)
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;
}
@@ -6383,6 +6379,26 @@ aligned_deallocation_fn_p (tree t)
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
deallocation function (3.7.4.2 [basic.stc.dynamic.deallocation]). */
@@ -6395,13 +6411,11 @@ usual_deallocation_fn_p (tree t)
|| primary_template_specialization_p (t))
return false;
- /* If a class T has a member deallocation function named operator delete
- with exactly one parameter, then that function is a usual
- (non-placement) deallocation function. If class T does not declare
- such an operator delete but does declare a member deallocation
- function named operator delete with exactly two parameters, the second
- of which has type std::size_t (18.2), then this function is a usual
- deallocation function. */
+ /* A usual deallocation function is a deallocation function whose parameters
+ after the first are
+ - optionally, a parameter of type std::destroying_delete_t, then
+ - optionally, a parameter of type std::size_t, then
+ - optionally, a parameter of type std::align_val_t. */
bool global = DECL_NAMESPACE_SCOPE_P (t);
tree chain = FUNCTION_ARG_CHAIN (t);
if (!chain)
@@ -6410,7 +6424,7 @@ usual_deallocation_fn_p (tree t)
chain = TREE_CHAIN (chain);
if (chain == void_list_node
|| ((!global || flag_sized_deallocation)
- && second_parm_is_size_t (t)))
+ && sized_deallocation_fn_p (t)))
return true;
if (aligned_deallocation_fn_p (t))
return true;
@@ -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. */
want_size = false;
}
- bool fn_size = second_parm_is_size_t (fn);
- bool elt_size = second_parm_is_size_t (elt);
+ 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;
@@ -6682,7 +6696,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
args->quick_push (addr);
if (destroying)
args->quick_push (destroying);
- if (second_parm_is_size_t (fn))
+ if (sized_deallocation_fn_p (fn))
args->quick_push (size);
if (aligned_deallocation_fn_p (fn))
{
new file mode 100644
@@ -0,0 +1,11 @@
+// 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; }
@@ -1,3 +1,10 @@
+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 Jakub Jelinek <jakub@redhat.com>
PR c++/90108