re PR tree-optimization/47290 (memory exhausted compiling a destructor with an infini...
authorJakub Jelinek <jakub@redhat.com>
Tue, 18 Jan 2011 23:16:16 +0000 (00:16 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 18 Jan 2011 23:16:16 +0000 (00:16 +0100)
PR tree-optimization/47290
* tree-eh.c (infinite_empty_loop_p): New function.
(cleanup_empty_eh): Use it.

* g++.dg/torture/pr47290.C: New test.

From-SVN: r168974

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

index 6c72e692bbf9b20bde326a7ec680aa3bec919114..c456fb34f5bd34ef4feaf863d40813243e0db9f1 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/47290
+       * tree-eh.c (infinite_empty_loop_p): New function.
+       (cleanup_empty_eh): Use it.
+
 2011-01-18  Steve Ellcey  <sje@cup.hp.com>
 
        PR target/46997
index 9c3e8ba99d03fbc60f5f54c77d4b6c7484f6b75f..550aee1cef626baf7be726d48e65367aae2bcef6 100644 (file)
@@ -1,3 +1,8 @@
+2011-01-19  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/47290
+       * g++.dg/torture/pr47290.C: New test.
+
 2011-01-18  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/47240
diff --git a/gcc/testsuite/g++.dg/torture/pr47290.C b/gcc/testsuite/g++.dg/torture/pr47290.C
new file mode 100644 (file)
index 0000000..b739de5
--- /dev/null
@@ -0,0 +1,19 @@
+// PR tree-optimization/47290
+// { dg-do compile }
+
+struct V
+{
+  V (int = 0);
+  ~V ()
+  {
+    for (;;)
+      ;
+  }
+  int size ();
+};
+
+struct S
+{
+  V a, b;
+  S () : b (a.size ()) {}
+} s;
index 270d76d9480d882f7a85327c652945599583c3a4..65d0ff2f9fd903f8ea8917fdd15eb228ca0fc81b 100644 (file)
@@ -1,5 +1,5 @@
 /* Exception handling semantics and decomposition for trees.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -3724,6 +3724,42 @@ cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
   return false;
 }
 
+/* Return true if edge E_FIRST is part of an empty infinite loop
+   or leads to such a loop through a series of single successor
+   empty bbs.  */
+
+static bool
+infinite_empty_loop_p (edge e_first)
+{
+  bool inf_loop = false;
+  edge e;
+
+  if (e_first->dest == e_first->src)
+    return true;
+
+  e_first->src->aux = (void *) 1;
+  for (e = e_first; single_succ_p (e->dest); e = single_succ_edge (e->dest))
+    {
+      gimple_stmt_iterator gsi;
+      if (e->dest->aux)
+       {
+         inf_loop = true;
+         break;
+       }
+      e->dest->aux = (void *) 1;
+      gsi = gsi_after_labels (e->dest);
+      if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi)))
+       gsi_next_nondebug (&gsi);
+      if (!gsi_end_p (gsi))
+       break;
+    }
+  e_first->src->aux = NULL;
+  for (e = e_first; e->dest->aux; e = single_succ_edge (e->dest))
+    e->dest->aux = NULL;
+
+  return inf_loop;
+}
+
 /* Examine the block associated with LP to determine if it's an empty
    handler for its EH region.  If so, attempt to redirect EH edges to
    an outer region.  Return true the CFG was updated in any way.  This
@@ -3763,7 +3799,7 @@ cleanup_empty_eh (eh_landing_pad lp)
   if (gsi_end_p (gsi))
     {
       /* For the degenerate case of an infinite loop bail out.  */
-      if (e_out->dest == bb)
+      if (infinite_empty_loop_p (e_out))
        return false;
 
       return cleanup_empty_eh_unsplit (bb, e_out, lp);