]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/42739 (ICE with computed goto, destructors, and optimization)
authorRichard Guenther <rguenther@suse.de>
Fri, 15 Jan 2010 11:53:26 +0000 (11:53 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 15 Jan 2010 11:53:26 +0000 (11:53 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr42739.C [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c

index e72f321b6c339cd7a56e88bd2247854a8c9b8575..a13093ee28ef844a1d69460c688dc6d7a403f13b 100644 (file)
@@ -1,3 +1,11 @@
+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.
index ba2aa6cc848a4304551d326bf03992ff703f2ca3..990ea36bf0983761f5f3b4ed7c47d1dc94e69df7 100644 (file)
@@ -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 (file)
index 0000000..ccc05f8
--- /dev/null
@@ -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;
+}
index 4ba9dd7325bf078ba713fe8b9f6382c6ba9859bc..0a3d544eece34b61c610d04c4dfb5e0641991801 100644 (file)
@@ -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 ");
index 9fb489a743dac8548a53604f9eab07ef65581cfd..5904407a35b59ed04a7dcc7a6f36727910613eb9 100644 (file)
@@ -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);
        }