diff options
author | Jason Merrill <jason@redhat.com> | 2019-04-20 02:18:30 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2019-04-20 02:18:30 -0400 |
commit | d395d8e771fce88e46e5c3908e53669adb5b71c4 (patch) | |
tree | 76e47dc2a375b689c261b98bd13908eab3711885 /gcc | |
parent | f9eff98e6fd81e72f662f721f31b99d6f8db5f7e (diff) | |
download | gcc-d395d8e771fce88e46e5c3908e53669adb5b71c4.zip gcc-d395d8e771fce88e46e5c3908e53669adb5b71c4.tar.gz gcc-d395d8e771fce88e46e5c3908e53669adb5b71c4.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 44 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C | 11 |
3 files changed, 47 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8eb2953..9e2c466 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 Paolo Carlini <paolo.carlini@oracle.com> PR c++/89900 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9582345..f27a80d 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 0000000..c122cee --- /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 <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; } |