aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArsen Arsenović <arsen@aarsen.me>2024-08-16 19:07:01 +0200
committerArsen Arsenović <arsen@gcc.gnu.org>2024-08-29 13:53:33 +0200
commitd9c54e9a036189e8961ec17e118fccf794d7bfab (patch)
treebc5519633349392ee78f596f22ffe38a7a376fde /gcc
parentbd2ccc24420c0789a3ad0b49d0ea4c2e7653afae (diff)
downloadgcc-d9c54e9a036189e8961ec17e118fccf794d7bfab.zip
gcc-d9c54e9a036189e8961ec17e118fccf794d7bfab.tar.gz
gcc-d9c54e9a036189e8961ec17e118fccf794d7bfab.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/coroutine-passes.cc26
-rw-r--r--gcc/testsuite/g++.dg/coroutines/torture/pr105104.C40
2 files changed, 40 insertions, 26 deletions
diff --git a/gcc/coroutine-passes.cc b/gcc/coroutine-passes.cc
index 9124eca..0f8e24f 100644
--- a/gcc/coroutine-passes.cc
+++ b/gcc/coroutine-passes.cc
@@ -294,9 +294,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;
@@ -384,8 +381,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. */
@@ -473,27 +468,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 0000000..fcc783e
--- /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 ();