https://gcc.gnu.org/g:5a275b5bebdf7746af590fa57378cd48cb8e679a

commit r14-11731-g5a275b5bebdf7746af590fa57378cd48cb8e679a
Author: Arsen Arsenović <ar...@aarsen.me>
Date:   Fri Aug 16 19:07:01 2024 +0200

    c++: don't remove labels during coro-early-expand-ifns [PR105104]
    
    In some scenarios, it is possible for the CFG cleanup to cause one of
    the labels mentioned in CO_YIELD, which coro-early-expand-ifns intends
    to remove, to become part of some statement.  As a result, when that
    label is removed, the statement it became part of becomes invalid,
    crashing the compiler.
    
    There doesn't appear to be a reason to remove the labels (anymore, at
    least), so let's not do that.
    
            PR c++/105104
    
    gcc/ChangeLog:
    
            * coroutine-passes.cc (execute_early_expand_coro_ifns): Don't
            remove any labels.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/torture/pr105104.C: New test.
    
    (cherry picked from commit d9c54e9a036189e8961ec17e118fccf794d7bfab)

Diff:
---
 gcc/coroutine-passes.cc                            | 26 --------------
 gcc/testsuite/g++.dg/coroutines/torture/pr105104.C | 40 ++++++++++++++++++++++
 2 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/gcc/coroutine-passes.cc b/gcc/coroutine-passes.cc
index c0d6eca7c070..b962d7598c43 100644
--- a/gcc/coroutine-passes.cc
+++ b/gcc/coroutine-passes.cc
@@ -293,9 +293,6 @@ execute_early_expand_coro_ifns (void)
   /* Some of the possible YIELD points will hopefully have been removed by
      earlier optimisations; record the ones that are still present.  */
   hash_map<int_hash<HOST_WIDE_INT, -1, -2>, tree> destinations;
-  /* Labels we added to carry the CFG changes, we need to remove these to
-     avoid confusing EH.  */
-  hash_set<tree> to_remove;
   /* List of dispatch points to update.  */
   auto_vec<gimple_stmt_iterator, 16> actor_worklist;
   basic_block bb;
@@ -374,8 +371,6 @@ execute_early_expand_coro_ifns (void)
                }
              else
                dst_dest = dst_tgt;
-             to_remove.add (res_tgt);
-             to_remove.add (dst_tgt);
              /* lose the co_yield.  */
              gsi_remove (&gsi, true);
              stmt = gsi_stmt (gsi); /* next. */
@@ -463,27 +458,6 @@ execute_early_expand_coro_ifns (void)
        }
     }
 
-  /* Remove the labels we inserted to map our hidden CFG, this
-     avoids confusing block merges when there are also EH labels.  */
-  FOR_EACH_BB_FN (bb, cfun)
-    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
-      {
-       gimple *stmt = gsi_stmt (gsi);
-       if (glabel *glab = dyn_cast<glabel *> (stmt))
-         {
-           tree rem = gimple_label_label (glab);
-           if (to_remove.contains (rem))
-             {
-               gsi_remove (&gsi, true);
-               to_remove.remove (rem);
-               continue; /* We already moved to the next insn.  */
-             }
-         }
-       else
-         break;
-       gsi_next (&gsi);
-      }
-
   /* Changed the CFG.  */
   todoflags |= TODO_cleanup_cfg;
   return todoflags;
diff --git a/gcc/testsuite/g++.dg/coroutines/torture/pr105104.C 
b/gcc/testsuite/g++.dg/coroutines/torture/pr105104.C
new file mode 100644
index 000000000000..fcc783e3066d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/torture/pr105104.C
@@ -0,0 +1,40 @@
+// https://gcc.gnu.org/PR105104
+// { dg-additional-options "-O" }
+
+#include <coroutine>
+
+// ICE during GIMPLE pass: coro-early-expand-ifs. final_awaiter::await_resume 
is
+// non-void, and optimizations are enabled.
+
+struct return_object
+{
+  struct promise_type
+  {
+    static constexpr std::suspend_always initial_suspend () noexcept
+    {
+      return {};
+    }
+
+    struct final_awaiter
+    {
+      static constexpr bool await_ready () noexcept { return false; }
+      static constexpr void await_suspend (std::coroutine_handle<>) noexcept {}
+      static constexpr int await_resume () noexcept { return {}; }
+    };
+    static constexpr final_awaiter final_suspend () noexcept { return {}; }
+
+    static void unhandled_exception () { throw; }
+
+    return_object get_return_object () { return {}; }
+
+    static constexpr void return_void () noexcept {}
+  };
+};
+
+return_object
+coroutine ()
+{
+  co_return;
+}
+
+return_object f = coroutine ();

Reply via email to