aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-12-23 16:34:12 -0700
committerMartin Sebor <msebor@redhat.com>2020-12-23 16:38:18 -0700
commit0df311657dc8c2a7f6ce3464c9d9ae5d5033840c (patch)
tree4a2119942f2ded72bcc6080776e8320ecb18ab45
parentfdd8560cce9f10fe5dcd26483440be136b81701d (diff)
downloadgcc-0df311657dc8c2a7f6ce3464c9d9ae5d5033840c.zip
gcc-0df311657dc8c2a7f6ce3464c9d9ae5d5033840c.tar.gz
gcc-0df311657dc8c2a7f6ce3464c9d9ae5d5033840c.tar.bz2
PR middle-end/98160 - ICE in warn_dealloc_offset on member placement new and delete
gcc/ChangeLog: PR middle-end/98160 * builtins.c (warn_dealloc_offset): Avoid assuming calls are made through declared functions and not pointers. gcc/testsuite/ChangeLog: PR middle-end/98160 * g++.dg/warn/pr98160.C: New test.
-rw-r--r--gcc/builtins.c4
-rw-r--r--gcc/testsuite/g++.dg/warn/pr98160.C30
2 files changed, 33 insertions, 1 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 498a112..ffbb9b7 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -13400,6 +13400,8 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
return false;
tree dealloc_decl = get_callee_fndecl (exp);
+ if (!dealloc_decl)
+ return false;
if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
&& !DECL_IS_REPLACEABLE_OPERATOR (dealloc_decl))
@@ -13413,7 +13415,7 @@ warn_dealloc_offset (location_t loc, tree exp, const access_ref &aref)
if (is_gimple_call (def_stmt))
{
tree alloc_decl = gimple_call_fndecl (def_stmt);
- if (!DECL_IS_OPERATOR_NEW_P (alloc_decl))
+ if (!alloc_decl || !DECL_IS_OPERATOR_NEW_P (alloc_decl))
return false;
}
}
diff --git a/gcc/testsuite/g++.dg/warn/pr98160.C b/gcc/testsuite/g++.dg/warn/pr98160.C
new file mode 100644
index 0000000..b3c5783
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr98160.C
@@ -0,0 +1,30 @@
+/* PR middle-end/98160 - ICE in warn_dealloc_offset on member placement
+ new and delete
+ { dg-do compile }
+ { dg-options "-O2 -Wall" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+void* (*pf) (size_t);
+
+struct A;
+struct B
+{
+ B ();
+
+ void* operator new (size_t, A*);
+ void operator delete (void*, A*);
+};
+
+void operator delete (void *, A*);
+
+void B::operator delete (void*, A *p)
+{
+ void *q = pf (1);
+ ::operator delete ((char*)q + 1, p);
+}
+
+void* f (A *p)
+{
+ return new (p) B;
+}