aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2015-03-31 09:34:08 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2015-03-31 09:34:08 +0000
commitbed18fbd09667cbaecc3b8a99e05801a24e5324b (patch)
treedc7fac5fb06b3487d74ab50ff205bb9f9b3b5bc5 /gcc
parent20f234a8d6b6bff86e9f57e66a2d3612f81e56e1 (diff)
downloadgcc-bed18fbd09667cbaecc3b8a99e05801a24e5324b.zip
gcc-bed18fbd09667cbaecc3b8a99e05801a24e5324b.tar.gz
gcc-bed18fbd09667cbaecc3b8a99e05801a24e5324b.tar.bz2
re PR c++/65626 (ICE in fixup_noreturn_call called by tree-ssa-forwprop.c:2492)
2015-03-31 Richard Biener <rguenther@suse.de> PR middle-end/65626 * tree-cfgcleanup.c (fixup_noreturn_call): Only split the block of the noreturn call so it is last and cleanup_control_flow_bb can do the CFG part. * g++.dg/torture/pr65626.C: New testcase. From-SVN: r221790
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr65626.C19
-rw-r--r--gcc/tree-cfgcleanup.c19
4 files changed, 45 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 189c3d8..36d8370 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2015-03-31 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/65626
+ * tree-cfgcleanup.c (fixup_noreturn_call): Only split the block
+ of the noreturn call so it is last and cleanup_control_flow_bb
+ can do the CFG part.
+
2015-03-31 Ilya Enkovich <ilya.enkovich@intel.com>
PR target/65531
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index de247ed..f8adda1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-03-31 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/65626
+ * g++.dg/torture/pr65626.C: New testcase.
+
2015-03-31 Ilya Enkovich <ilya.enkovich@intel.com>
PR target/65531
diff --git a/gcc/testsuite/g++.dg/torture/pr65626.C b/gcc/testsuite/g++.dg/torture/pr65626.C
new file mode 100644
index 0000000..ed85ba9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr65626.C
@@ -0,0 +1,19 @@
+// { dg-do compile }
+
+class A {
+ virtual unsigned long m_fn1() const;
+ virtual int &m_fn2(unsigned long) const;
+};
+class C : A {
+public:
+ int &m_fn2(unsigned long) const;
+ unsigned long m_fn1() const;
+};
+class B {
+ void m_fn3(const A &, const int &, const C &, int &) const;
+};
+void B::m_fn3(const A &, const int &, const C &, int &) const {
+ C &a(a);
+ for (long b = 0; a.m_fn1(); b++)
+ a.m_fn2(0);
+}
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index e7122e3..26258aa 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -579,13 +579,15 @@ remove_forwarder_block (basic_block bb)
return true;
}
-/* STMT is a call that has been discovered noreturn. Fixup the CFG
- and remove LHS. Return true if something changed. */
+/* STMT is a call that has been discovered noreturn. Split the
+ block to prepare fixing up the CFG and remove LHS.
+ Return true if cleanup-cfg needs to run. */
bool
fixup_noreturn_call (gimple stmt)
{
basic_block bb = gimple_bb (stmt);
+ bool changed = false;
if (gimple_call_builtin_p (stmt, BUILT_IN_RETURN))
return false;
@@ -604,7 +606,10 @@ fixup_noreturn_call (gimple stmt)
gsi_remove (&gsi, true);
}
else
- split_block (bb, stmt);
+ {
+ split_block (bb, stmt);
+ changed = true;
+ }
}
/* If there is an LHS, remove it. */
@@ -626,9 +631,13 @@ fixup_noreturn_call (gimple stmt)
}
/* Mark the call as altering control flow. */
- gimple_call_set_ctrl_altering (stmt, true);
+ if (!gimple_call_ctrl_altering_p (stmt))
+ {
+ gimple_call_set_ctrl_altering (stmt, true);
+ changed = true;
+ }
- return remove_fallthru_edge (bb->succs);
+ return changed;
}