aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2010-01-15 11:53:26 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2010-01-15 11:53:26 +0000
commit1197e78957aea05816665f843e4a0b936c847e07 (patch)
tree67ed89e55330179795b12967f60c0b05168d6454
parent58be9ce9c30e0b16d4d4cb6ccccc4b910b8ae834 (diff)
downloadgcc-1197e78957aea05816665f843e4a0b936c847e07.zip
gcc-1197e78957aea05816665f843e4a0b936c847e07.tar.gz
gcc-1197e78957aea05816665f843e4a0b936c847e07.tar.bz2
re PR middle-end/42739 (ICE with computed goto, destructors, and optimization)
2010-01-15 Richard Guenther <rguenther@suse.de> PR middle-end/42739 * tree-cfgcleanup.c (remove_forwarder_block): Move destination labels of computed or non-local gotos to the destination. * tree-cfg.c (gimple_verify_flow_info): Verify that a EH landing pad label is the first label. * g++.dg/torture/pr42739.C: New testcase. From-SVN: r155937
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr42739.C16
-rw-r--r--gcc/tree-cfg.c9
-rw-r--r--gcc/tree-cfgcleanup.c53
5 files changed, 74 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e72f321..a13093e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2010-01-15 Richard Guenther <rguenther@suse.de>
+ PR middle-end/42739
+ * tree-cfgcleanup.c (remove_forwarder_block): Move destination
+ labels of computed or non-local gotos to the destination.
+ * tree-cfg.c (gimple_verify_flow_info): Verify that a EH
+ landing pad label is the first label.
+
+2010-01-15 Richard Guenther <rguenther@suse.de>
+
* tree-ssa-loop-im.c (gen_lsm_tmp_name): Fix bogus fallthru.
2010-01-14 Michael Meissner <meissner@linux.vnet.ibm.com>
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ba2aa6c..990ea36 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-01-15 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/42739
+ * g++.dg/torture/pr42739.C: New testcase.
+
2010-01-15 Dodji Seketeli <dodji@redhat.com>
* g++.dg/template/error45.C: Revert as part of reverting changes
diff --git a/gcc/testsuite/g++.dg/torture/pr42739.C b/gcc/testsuite/g++.dg/torture/pr42739.C
new file mode 100644
index 0000000..ccc05f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr42739.C
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+struct s { ~s() { s(); } };
+
+int f()
+{
+ M:
+ s o = s();
+ f();
+ f();
+
+ L:
+ goto *(f() ? &&L : &&M);
+
+ return 0;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 4ba9dd7..0a3d544 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4268,6 +4268,15 @@ gimple_verify_flow_info (void)
err = 1;
}
+ if (prev_stmt && EH_LANDING_PAD_NR (label) != 0)
+ {
+ error ("EH landing pad label ");
+ print_generic_expr (stderr, label, 0);
+ fprintf (stderr, " is not first in a sequence of labels in bb %d",
+ bb->index);
+ err = 1;
+ }
+
if (label_to_block (label) != bb)
{
error ("label ");
diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c
index 9fb489a..5904407 100644
--- a/gcc/tree-cfgcleanup.c
+++ b/gcc/tree-cfgcleanup.c
@@ -338,7 +338,6 @@ remove_forwarder_block (basic_block bb)
gimple label;
edge_iterator ei;
gimple_stmt_iterator gsi, gsi_to;
- bool seen_abnormal_edge = false;
/* We check for infinite loops already in tree_forwarder_block_p.
However it may happen that the infinite loop is created
@@ -365,14 +364,10 @@ remove_forwarder_block (basic_block bb)
So if there is an abnormal edge to BB, proceed only if there is
no abnormal edge to DEST and there are no phi nodes in DEST. */
- if (has_abnormal_incoming_edge_p (bb))
- {
- seen_abnormal_edge = true;
-
- if (has_abnormal_incoming_edge_p (dest)
- || !gimple_seq_empty_p (phi_nodes (dest)))
- return false;
- }
+ if (has_abnormal_incoming_edge_p (bb)
+ && (has_abnormal_incoming_edge_p (dest)
+ || !gimple_seq_empty_p (phi_nodes (dest))))
+ return false;
/* If there are phi nodes in DEST, and some of the blocks that are
predecessors of BB are also predecessors of DEST, check that the
@@ -419,16 +414,40 @@ remove_forwarder_block (basic_block bb)
}
}
- if (seen_abnormal_edge)
+ /* Move nonlocal labels and computed goto targets as well as user
+ defined labels and labels with an EH landing pad number to the
+ new block, so that the redirection of the abnormal edges works,
+ jump targets end up in a sane place and debug information for
+ labels is retained. */
+ gsi_to = gsi_start_bb (dest);
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+ {
+ tree decl;
+ label = gsi_stmt (gsi);
+ if (is_gimple_debug (label))
+ break;
+ decl = gimple_label_label (label);
+ if (EH_LANDING_PAD_NR (decl) != 0
+ || DECL_NONLOCAL (decl)
+ || FORCED_LABEL (decl)
+ || !DECL_ARTIFICIAL (decl))
+ {
+ gsi_remove (&gsi, false);
+ gsi_insert_before (&gsi_to, label, GSI_SAME_STMT);
+ }
+ else
+ gsi_next (&gsi);
+ }
+
+ /* Move debug statements if the destination has just a single
+ predecessor. */
+ if (single_pred_p (dest))
{
- /* Move the labels to the new block, so that the redirection of
- the abnormal edges works. */
- gsi_to = gsi_start_bb (dest);
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+ gsi_to = gsi_after_labels (dest);
+ for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); )
{
- label = gsi_stmt (gsi);
- gcc_assert (gimple_code (label) == GIMPLE_LABEL
- || is_gimple_debug (label));
+ if (!is_gimple_debug (gsi_stmt (gsi)))
+ break;
gsi_remove (&gsi, false);
gsi_insert_before (&gsi_to, label, GSI_SAME_STMT);
}