We currently ignore all delete calls from delete expressions for
the purpose of generating PTA constraints. That's in error from
r11-3612-g4f4ced28826ece which did a tree-wide change to clarify
and improve eliding of new/delete pairs. The following restores
the original restriction of only ignoring calls to the standard
library copy of delete. This also adds a check on
-fassume-sane-operators-new-delete (which is the default).
Bootstrap / regtest ongoing on x86_64-unknown-linux-gnu.
v2: add check on -fassume-sane-operators-new-delete as suggested
by Jason in the bugzilla trail
PR tree-optimization/126194
* gimple-ssa-pta-constraints.cc (find_func_aliases_for_call):
Only ignore calls to delete if DECL_IS_REPLACEABLE_OPERATOR.
* g++.dg/lto/pr126194.h: New testcase.
* g++.dg/lto/pr126194_0.C: Likewise.
* g++.dg/lto/pr126194_1.C: Likewise.
* g++.dg/lto/pr126194_2.C: Likewise.
---
gcc/gimple-ssa-pta-constraints.cc | 2 +
gcc/testsuite/g++.dg/lto/pr126194.h | 87 +++++++++++++++++++++++++++
gcc/testsuite/g++.dg/lto/pr126194_0.C | 71 ++++++++++++++++++++++
gcc/testsuite/g++.dg/lto/pr126194_1.C | 41 +++++++++++++
gcc/testsuite/g++.dg/lto/pr126194_2.C | 8 +++
5 files changed, 209 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/lto/pr126194.h
create mode 100644 gcc/testsuite/g++.dg/lto/pr126194_0.C
create mode 100644 gcc/testsuite/g++.dg/lto/pr126194_1.C
create mode 100644 gcc/testsuite/g++.dg/lto/pr126194_2.C
diff --git a/gcc/gimple-ssa-pta-constraints.cc
b/gcc/gimple-ssa-pta-constraints.cc
index a377b891d80..b433aee8243 100644
--- a/gcc/gimple-ssa-pta-constraints.cc
+++ b/gcc/gimple-ssa-pta-constraints.cc
@@ -2150,7 +2150,9 @@ find_func_aliases_for_call (struct function *fn, gcall *t)
such operator, then the effects for PTA (in particular
the escaping of the pointer) can be ignored. */
else if (fndecl
+ && flag_assume_sane_operators_new_delete
&& DECL_IS_OPERATOR_DELETE_P (fndecl)
+ && DECL_IS_REPLACEABLE_OPERATOR (fndecl)
&& gimple_call_from_new_or_delete (t))
;
else
diff --git a/gcc/testsuite/g++.dg/lto/pr126194.h
b/gcc/testsuite/g++.dg/lto/pr126194.h
new file mode 100644
index 00000000000..21db1d9885d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr126194.h
@@ -0,0 +1,87 @@
+#pragma once
+
+using Size = decltype(sizeof(0));
+
+struct A
+{
+ void (*const f_)(void**) noexcept;
+ void** const p_;
+ Size const a_;
+
+ A(void** pp, void (*f)(void**) noexcept, Size a) noexcept
+ : f_(f), p_(pp), a_(a) {}
+
+ void reset() const noexcept
+ {
+ if (*p_) {
+ (*f_)(p_);
+ }
+ }
+
+ A& operator=(const A&) = delete;
+
+ void* create(Size size, const void* caller, struct R& r) const;
+ void destroy(void* p, const void* caller, struct R& r) const noexcept;
+};
+
+struct R
+{
+ virtual ~R() = default;
+ virtual void* allocate(Size size, const void* caller) = 0;
+ virtual void deallocate(void* p, const void* caller) noexcept = 0;
+};
+
+R& get_r() noexcept;
+void touch(const void* p) noexcept;
+
+struct B
+{
+ void* q = nullptr;
+
+ static void cb(void** pp) noexcept
+ {
+ B* self = reinterpret_cast<B*>(pp);
+ if (self->q) {
+ extern void release_q(void*);
+ release_q(self->q);
+ }
+ self->q = nullptr;
+ }
+
+ ~B() noexcept
+ {
+ touch(this);
+ if (q) {
+ extern void release_q(void*);
+ release_q(q);
+ }
+ }
+
+ B() noexcept = default;
+ B(const B&) = delete;
+ B& operator=(const B&) = delete;
+ B(B&& other) noexcept : q(other.q)
+ {
+ other.q = nullptr;
+ }
+ B& operator=(B&& other) noexcept
+ {
+ if (this != &other) {
+ if (q) {
+ extern void release_q(void*);
+ release_q(q);
+ }
+ q = other.q;
+ other.q = nullptr;
+ }
+ return *this;
+ }
+
+ operator A() noexcept
+ {
+ return A(&q, &cb, alignof(void*));
+ }
+};
+
+void* operator new(Size size, A const& a, R& r) noexcept(false);
+void operator delete(void* p, A const& a, R& r) noexcept;
diff --git a/gcc/testsuite/g++.dg/lto/pr126194_0.C
b/gcc/testsuite/g++.dg/lto/pr126194_0.C
new file mode 100644
index 00000000000..b7c85039862
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr126194_0.C
@@ -0,0 +1,71 @@
+// { dg-lto-do run }
+// { dg-lto-options { { -O2 -flto } } }
+
+#include "pr126194.h"
+
+extern "C" void* malloc(Size size) noexcept;
+extern "C" void free(void* p) noexcept;
+
+namespace {
+class M final : public R
+{
+public:
+ void* allocate(Size size, const void* /*caller*/) override
+ {
+ return malloc(size);
+ }
+
+ void deallocate(void* p, const void* /*caller*/) noexcept override
+ {
+ free(p);
+ }
+};
+
+M g_r;
+}
+
+R& get_r() noexcept
+{
+ return g_r;
+}
+
+void touch(const void* p) noexcept
+{
+ static const volatile void* sink = nullptr;
+ sink = p;
+}
+
+void release_q(void* p)
+{
+ free(p);
+}
+
+int g_should_throw = 0;
+
+void* A::create(Size size, const void* caller, R& r) const
+{
+ reset();
+ if (size < a_) size = a_;
+ void* p = r.allocate(size, caller);
+ if (!p) throw 2;
+ *p_ = p;
+ return p;
+}
+
+__attribute__((noinline))
+void A::destroy(void* p, const void* caller, R& r) const noexcept
+{
+ *p_ = nullptr;
+ r.deallocate(p, caller);
+}
+
+void* operator new(Size size, A const& a, R& r) noexcept(false)
+{
+ return a.create(size, __builtin_return_address(0), r);
+}
+
+__attribute__((noinline))
+void operator delete(void* p, A const& a, R& r) noexcept
+{
+ a.destroy(p, __builtin_return_address(0), r);
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr126194_1.C
b/gcc/testsuite/g++.dg/lto/pr126194_1.C
new file mode 100644
index 00000000000..e2894cd0105
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr126194_1.C
@@ -0,0 +1,41 @@
+#include "pr126194.h"
+
+extern int g_should_throw;
+
+struct T
+{
+ int a;
+ __attribute__((noinline)) T() : a(0)
+ {
+ if (g_should_throw) {
+ throw 1;
+ }
+ }
+};
+
+__attribute__((noinline))
+int make_widget(bool go, void** out_ptr)
+{
+ B b;
+ R& r = get_r();
+ if (go) {
+ T* t = new(b, r) T();
+ (void)t;
+ }
+ *out_ptr = b.q;
+ b.q = nullptr;
+ return 42;
+}
+
+extern "C" __attribute__((visibility("default")))
+int run_repro(int argc)
+{
+ g_should_throw = (argc > 0);
+ void* p = nullptr;
+ try {
+ (void)make_widget(argc > 0, &p);
+ return 1;
+ } catch (...) {
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr126194_2.C
b/gcc/testsuite/g++.dg/lto/pr126194_2.C
new file mode 100644
index 00000000000..3c024f47a19
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr126194_2.C
@@ -0,0 +1,8 @@
+// { dg-options "-fno-lto" }
+
+extern "C" int run_repro(int argc);
+
+int main(int argc, char**)
+{
+ return run_repro(argc);
+}
--
2.51.0