aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/PR58294.C20
-rw-r--r--gcc/value-prof.c30
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;
}