From d395d8e771fce88e46e5c3908e53669adb5b71c4 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 20 Apr 2019 02:18:30 -0400 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 7 +++ gcc/cp/call.c | 44 ++++++++++++------- .../g++.dg/cpp2a/destroying-delete4.C | 11 +++++ 3 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8eb2953e051..9e2c46624de 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-04-19 Jason Merrill + + 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 PR c++/89900 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9582345d7e8..f27a80dfa3b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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)) { diff --git a/gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C b/gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C new file mode 100644 index 00000000000..c122cee4942 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C @@ -0,0 +1,11 @@ +// PR c++/90171 +// { dg-do compile { target c++2a } } + +#include + +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; } -- 2.30.2