c++: Fix ICE due to shared BLOCK node in coroutine generation [PR103328]
authorBenno Evers <benno.evers@tenzir.com>
Sat, 2 Apr 2022 16:22:33 +0000 (17:22 +0100)
committerIain Sandoe <iain@sandoe.co.uk>
Sun, 3 Apr 2022 09:10:13 +0000 (10:10 +0100)
commit0847ad33b908af88bca1e6980d0b977316d05e18
tree9b793745e615e8dcbd26f137f49e7706957a4efb
parent235d5a96cb8dad0b4c427602346fcf966a4ec914
c++: Fix ICE due to shared BLOCK node in coroutine generation [PR103328]

When finishing a function that is a coroutine, the function is
transformed into a "ramp" function, and the original user-provided
function body gets moved into a newly created "actor" function.

In this case `current_function_decl` points to the ramp function,
but `current_binding_level->blocks` would still point to the
scope block of the user-provided function body in the actor function,
so when the ramp function was finished during `poplevel()` in decl.cc,
we could end up with that block being reused as the `DECL_INITIAL()` of
the ramp function:

   subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
   // [...]
   DECL_INITIAL (current_function_decl) = block ? block : subblocks;

This block would then be independently modified by subsequent passes
touching either the ramp or the actor function, potentially causing
an ICE depending on the order and function of these passes.

gcc/cp/ChangeLog:

PR c++/103328
* coroutines.cc (morph_fn_to_coro): Reset
current_binding_level->blocks.

gcc/testsuite/ChangeLog:

PR c++/103328
* g++.dg/coroutines/pr103328.C: New test.

Co-Authored-By: Iain Sandoe <iain@sandoe.co.uk>
gcc/cp/coroutines.cc
gcc/testsuite/g++.dg/coroutines/pr103328.C [new file with mode: 0644]