https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128172
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Known to fail| |12.5.0, 13.4.0, 14.2.0,
| |14.4.0, 15.3.0, 16.2.0,
| |17.0, 7.5.0, 9.5.0
Keywords| |ice-on-invalid-code
See Also| |https://gcc.gnu.org/bugzill
| |a/show_bug.cgi?id=121870
--- Comment #1 from liu zhenyu <lzy20000419 at outlook dot com> ---
DOM propagates p == die into both indirect calls: p () in the body and (*q) ()
in the cleanup (the landing pad). die is found to be noreturn and nothrow, so
both calls are queued in need_noreturn_fixup (tree-ssa-dom.cc:2558 in 14.2,
:2322 in trunk). Then pass_dominator::execute does:
gcc/tree-ssa-dom.cc (trunk :872-890, 14.2 :1026-1044):
gimple_purge_all_dead_eh_edges (need_eh_cleanup);
...
while (!need_noreturn_fixup.is_empty ())
{
gimple *stmt = need_noreturn_fixup.pop ();
...
fixup_noreturn_call (stmt);
}
The EH purge removes the now-dead landing pad, which also removes the second
queued call. fixup_noreturn_call then gets a stmt with gimple_bb == NULL and
crashes in gsi_last_bb.
This is the same pattern as PR121870. Its fix (r16-3794, backported) added the
guard only to substitute_and_fold in tree-ssa-propagate.cc. DOM has the same
"purge, then fix up" order, but it didn't get the guard.
Suggested fix, same as PR121870:
gimple *stmt = need_noreturn_fixup.pop ();
+ /* The dead EH edge purge above may have removed STMT. */
+ if (!gimple_bb (stmt))
+ continue;
I tested this on 14.2. The C and C++ testcases and a -fnon-call-exceptions
variant no longer ICE.