diff options
author | Arsen Arsenović <arsen@aarsen.me> | 2024-08-16 19:07:01 +0200 |
---|---|---|
committer | Arsen Arsenović <arsen@gcc.gnu.org> | 2024-08-29 13:53:33 +0200 |
commit | d9c54e9a036189e8961ec17e118fccf794d7bfab (patch) | |
tree | bc5519633349392ee78f596f22ffe38a7a376fde /gcc | |
parent | bd2ccc24420c0789a3ad0b49d0ea4c2e7653afae (diff) | |
download | gcc-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.cc | 26 | ||||
-rw-r--r-- | 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 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 (); |