When a dead EH or abnormal edge makes a call queued for noreturn fixup
unreachable, just skip processing it.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/121870
        * tree-ssa-propagate.cc
        (substitute_and_fold_engine::substitute_and_fold): Skip
        removed stmts from noreturn fixup.

        * g++.dg/torture/pr121870.C: New testcase.
---
 gcc/testsuite/g++.dg/torture/pr121870.C | 20 ++++++++++++++++++++
 gcc/tree-ssa-propagate.cc               |  2 ++
 2 files changed, 22 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/torture/pr121870.C

diff --git a/gcc/testsuite/g++.dg/torture/pr121870.C 
b/gcc/testsuite/g++.dg/torture/pr121870.C
new file mode 100644
index 00000000000..8f4e7ab5069
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr121870.C
@@ -0,0 +1,20 @@
+__attribute__((noreturn)) void f1(void)
+{
+    while(true) {}
+}
+static void (*fptr)(void) = f1;
+struct s1
+{
+    ~s1() {
+        fptr();
+    }
+    void DoInner() {
+        fptr();
+    }
+};
+
+void f()
+{
+    s1 xxx;
+    xxx.DoInner();
+}
diff --git a/gcc/tree-ssa-propagate.cc b/gcc/tree-ssa-propagate.cc
index ec206894821..872f881b644 100644
--- a/gcc/tree-ssa-propagate.cc
+++ b/gcc/tree-ssa-propagate.cc
@@ -1019,6 +1019,8 @@ substitute_and_fold_engine::substitute_and_fold 
(basic_block block)
   while (!walker.stmts_to_fixup.is_empty ())
     {
       gimple *stmt = walker.stmts_to_fixup.pop ();
+      if (!gimple_bb (stmt))
+       continue;
       if (dump_file && dump_flags & TDF_DETAILS)
        {
          fprintf (dump_file, "Fixing up noreturn call ");
-- 
2.51.0

Reply via email to