diff --git a/gcc/testsuite/gcc.dg/pr108691.c b/gcc/testsuite/gcc.dg/pr108691.c new file mode 100644 index 0000000000000000000000000000000000000000..e412df10f22c2c196aa65ed6d8ec199a18a9d645 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr108691.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern int __attribute__((returns_twice)) setjmp(void*); + +void bbb(void) { + int (*fnptr)(void*) = setjmp; + fnptr(0); +} diff --git a/gcc/tree-ssa-dce.cc b/gcc/tree-ssa-dce.cc index ceeb0ad5ab3351a77caea5fd6940ea58347d6aab..0ae998f86f9839ba5a95c5fc1a22cd2f12b5cdad 100644 --- a/gcc/tree-ssa-dce.cc +++ b/gcc/tree-ssa-dce.cc @@ -1512,10 +1512,12 @@ eliminate_unnecessary_stmts (bool aggressive) remove_edge (to_remove_edges[i]); cfg_altered = true; } - /* When we cleared calls_setjmp we can purge all abnormal edges. Do so. */ - if (cfun->calls_setjmp != had_setjmp) + /* When we cleared calls_setjmp we can purge all abnormal edges. Do so. + ??? We'd like to assert that setjmp calls do not pop out of nothing + but we currently lack a per-stmt way of noting whether a call was + recognized as returns-twice (or rather receives-control). */ + if (!cfun->calls_setjmp && had_setjmp) { - gcc_assert (!cfun->calls_setjmp); /* Make sure we only remove the edges, not dominated blocks. Using gimple_purge_dead_abnormal_call_edges would do that and we cannot free dominators yet. */