re PR middle-end/40043 (ICE with nested try/catch)
authorJan Hubicka <jh@suse.cz>
Sat, 9 May 2009 10:52:24 +0000 (12:52 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 9 May 2009 10:52:24 +0000 (10:52 +0000)
* g++.dg/eh/nested-try.C: New test.

PR middle-end/40043
* except.c (copy_eh_region): Always set prev_try.
(redirect_eh_edge_to_label): Find outer try.
(foreach_reachable_handler): When looking for prev try
handle case where previous try is not going to be taken.

From-SVN: r147317

gcc/ChangeLog
gcc/except.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/eh/nested-try.C [new file with mode: 0644]

index dccd02fde0bd9d78a260461e08f4a49175921e25..2c5b52ee85cc455c28b03e053ff414a425b4c52a 100644 (file)
@@ -1,3 +1,11 @@
+2009-05-09  Jan Hubicka  <jh@suse.cz>
+
+       PR middle-end/40043
+       * except.c (copy_eh_region): Always set prev_try.
+       (redirect_eh_edge_to_label): Find outer try.
+       (foreach_reachable_handler): When looking for prev try
+       handle case where previous try is not going to be taken.
+
 2009-05-07  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR tree-optimization/40049
index 3ba3b67a1979c6115d7462a561490d3d9fe2c7b9..df28a9831d9fdaf6575ce4cf378771f00cdef369 100644 (file)
@@ -1410,9 +1410,9 @@ copy_eh_region (struct eh_region *old, struct eh_region *new_outer,
     {
       gcc_assert (old->type != ERT_TRY);
       r = copy_eh_region_1 (old, new_outer);
-      if (r->type == ERT_CLEANUP && prev_try_map)
+      if (r->type == ERT_CLEANUP)
         {
-         gcc_assert (r->u.cleanup.prev_try);
+         gcc_assert (r->u.cleanup.prev_try || !prev_try_map);
           r->u.cleanup.prev_try = prev_try_map;
        }
       return r;
@@ -1477,7 +1477,7 @@ struct eh_region *
 redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx,
                           bool inlinable_call, int region_number)
 {
-  struct eh_region *outer, *prev_try_map = NULL;
+  struct eh_region *outer, *prev_try_map;
   struct eh_region *region;
   VEC (eh_region, heap) * trace = NULL;
   int i;
@@ -1539,6 +1539,7 @@ redirect_eh_edge_to_label (edge e, tree new_dest_label, bool is_resx,
        }
       outer = VEC_index (eh_region, trace, start_here)->outer;
       gcc_assert (start_here >= 0);
+      prev_try_map = find_prev_try (outer);
 
       /* And now do the dirty job!  */
       for (i = start_here; i >= 0; i--)
@@ -3120,8 +3121,20 @@ foreach_reachable_handler (int region_number, bool is_resx, bool inlinable_call,
         to the next outer cleanup region, so the flow graph will be
         accurate.  */
       if (region->type == ERT_CLEANUP)
-       region = region->u.cleanup.prev_try;
-      else
+        {
+         enum reachable_code code = RNL_NOT_CAUGHT;
+         region = region->u.cleanup.prev_try;
+         /* Continue looking for outer TRY region until we find one
+            that might cath something.  */
+          while (region
+                && (code = reachable_next_level (region, type_thrown, &info,
+                                                 inlinable_call || is_resx))
+                    == RNL_NOT_CAUGHT)
+           region = find_prev_try (region->outer);
+         if (code >= RNL_CAUGHT)
+           break;
+       }
+      if (region)
        region = region->outer;
     }
 }
index 3099e1bded678453a70408e4a6ec7bca8642708a..c2fb1d3ccae34770d263719b24b410063f871594 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-09  Jan Hubicka  <jh@suse.cz>
+
+       PR middle-end/40043
+       * g++.dg/eh/nested-try.C: New test.
+
 2009-05-08  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR tree-optimization/40049
diff --git a/gcc/testsuite/g++.dg/eh/nested-try.C b/gcc/testsuite/g++.dg/eh/nested-try.C
new file mode 100644 (file)
index 0000000..5796f9a
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-do compile }
+// Nested try statements shadowing each other was crashing in EH edge redirection.
+// PR middle-end/40043
+struct A
+{
+  ~A();
+  void foo();
+};
+
+void bar()
+{
+  A a;
+
+  try
+  {
+    A b;
+
+    try
+    {
+      b.foo();
+    }
+    catch (int) {}
+  }
+  catch (int) {}
+}