diff options
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/PR58294.C | 20 | ||||
-rw-r--r-- | gcc/value-prof.c | 30 |
4 files changed, 45 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ab2bdd9..ceaf0e5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2013-09-09 Jan Hubicka <jh@suse.cz> + + PR middle-end/58294 + * value-prof.c (gimple_ic): Copy also abnormal edges. + 2013-09-09 Richard Sandiford <rdsandiford@googlemail.com> * asan.c (asan_shadow_cst): Use gen_int_mode. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 756611d..51cab1b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-09-09 Jan Hubicka <jh@suse.cz> + + PR middle-end/58294 + * g++.dg/torture/PR58294.C: New testcase. + 2013-09-08 Jeff Law <law@redhat.com> * gcc.c-torture/compile/pr58340.c: New test. diff --git a/gcc/testsuite/g++.dg/torture/PR58294.C b/gcc/testsuite/g++.dg/torture/PR58294.C new file mode 100644 index 0000000..e1fb95a --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/PR58294.C @@ -0,0 +1,20 @@ +// { dg-do compile } +struct A { + virtual ~A(); + virtual void m_fn1() { delete this; } + void m_fn2() { m_fn1(); } +}; + +struct B { + A *pi_; + B() { pi_->m_fn2(); } +}; +struct C { + B pn; +}; +void _setjmp(); +int png_decode() { + _setjmp(); + C a; + return 0; +} diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 3aa5c74..498eb90 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1299,6 +1299,9 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, edge e_cd, e_ci, e_di, e_dj = NULL, e_ij; gimple_stmt_iterator gsi; int lp_nr, dflags; + edge e_eh, e; + edge_iterator ei; + gimple_stmt_iterator psi; cond_bb = gimple_bb (icall_stmt); gsi = gsi_for_stmt (icall_stmt); @@ -1401,24 +1404,21 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, lp_nr = lookup_stmt_eh_lp (icall_stmt); if (lp_nr > 0 && stmt_could_throw_p (dcall_stmt)) { - edge e_eh, e; - edge_iterator ei; - gimple_stmt_iterator psi; - add_stmt_to_eh_lp (dcall_stmt, lp_nr); - FOR_EACH_EDGE (e_eh, ei, icall_bb->succs) - if (e_eh->flags & EDGE_EH) - break; - e = make_edge (dcall_bb, e_eh->dest, EDGE_EH); - for (psi = gsi_start_phis (e_eh->dest); - !gsi_end_p (psi); gsi_next (&psi)) - { - gimple phi = gsi_stmt (psi); - SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), - PHI_ARG_DEF_FROM_EDGE (phi, e_eh)); - } } + FOR_EACH_EDGE (e_eh, ei, icall_bb->succs) + if (e_eh->flags & (EDGE_EH | EDGE_ABNORMAL)) + { + e = make_edge (dcall_bb, e_eh->dest, e_eh->flags); + for (psi = gsi_start_phis (e_eh->dest); + !gsi_end_p (psi); gsi_next (&psi)) + { + gimple phi = gsi_stmt (psi); + SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), + PHI_ARG_DEF_FROM_EDGE (phi, e_eh)); + } + } return dcall_stmt; } |