aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-04-20 02:18:30 -0400
committerJason Merrill <jason@gcc.gnu.org>2019-04-20 02:18:30 -0400
commitd395d8e771fce88e46e5c3908e53669adb5b71c4 (patch)
tree76e47dc2a375b689c261b98bd13908eab3711885 /gcc
parentf9eff98e6fd81e72f662f721f31b99d6f8db5f7e (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/cp/call.c44
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/destroying-delete4.C11
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; }