When inlining a call that abnormally transfers control-flow we make all inlined calls that can possibly transfer abnormal control-flow do so as well. But we failed to mark the calls as altering control-flow. This results in inconsistent behavior later and possibly wrong-code (we'd eventually prune those edges).
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/119778 * tree-inline.cc (copy_edges_for_bb): Mark calls that are source of abnormal edges as altering control-flow. * g++.dg/torture/pr119778.C: New testcase. --- gcc/testsuite/g++.dg/torture/pr119778.C | 20 ++++++++++++++++++++ gcc/tree-inline.cc | 7 +++++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/torture/pr119778.C diff --git a/gcc/testsuite/g++.dg/torture/pr119778.C b/gcc/testsuite/g++.dg/torture/pr119778.C new file mode 100644 index 00000000000..49480561928 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr119778.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-additional-options "-Wall" } + +struct jmp_buf { long l[16]; }; +extern "C" int setjmp (jmp_buf *); +struct S { + void foo () { bar (); } + virtual char bar () { return 0; } +}; +void baz (); +jmp_buf *a; + +void +qux (bool x, S *y) +{ + if (x) + setjmp (a); + y->foo (); + baz (); +} diff --git a/gcc/tree-inline.cc b/gcc/tree-inline.cc index 05843b8ccf0..3289b4f6d05 100644 --- a/gcc/tree-inline.cc +++ b/gcc/tree-inline.cc @@ -2729,8 +2729,11 @@ copy_edges_for_bb (basic_block bb, profile_count num, profile_count den, && gimple_call_arg (copy_stmt, 0) == boolean_true_node) nonlocal_goto = false; else - make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest, - EDGE_ABNORMAL); + { + make_single_succ_edge (copy_stmt_bb, abnormal_goto_dest, + EDGE_ABNORMAL); + gimple_call_set_ctrl_altering (copy_stmt, true); + } } if ((can_throw || nonlocal_goto) -- 2.43.0