OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / tree-eh.c
index 3ea582f..965acce 100644 (file)
@@ -1,5 +1,6 @@
 /* Exception handling semantics and decomposition for trees.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software
+   Foundation, Inc.
 
 This file is part of GCC.
 
@@ -314,7 +315,7 @@ struct leh_tf_state
   size_t goto_queue_size;
   size_t goto_queue_active;
 
-  /* Pointer map to help in searching qoto_queue when it is large.  */
+  /* Pointer map to help in searching goto_queue when it is large.  */
   struct pointer_map_t *goto_queue_map;
 
   /* The set of unique labels seen as entries in the goto queue.  */
@@ -840,6 +841,23 @@ honor_protect_cleanup_actions (struct leh_state *outer_state,
   if (this_state)
     finally = lower_try_finally_dup_block (finally, outer_state);
 
+  /* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
+     set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
+     to be in an enclosing scope, but needs to be implemented at this level
+     to avoid a nesting violation (see wrap_temporary_cleanups in
+     cp/decl.c).  Since it's logically at an outer level, we should call
+     terminate before we get to it, so strip it away before adding the
+     MUST_NOT_THROW filter.  */
+  i = tsi_start (finally);
+  x = tsi_stmt (i);
+  if (protect_cleanup_actions
+      && TREE_CODE (x) == TRY_CATCH_EXPR
+      && TRY_CATCH_IS_CLEANUP (x))
+    {
+      tsi_link_before (&i, TREE_OPERAND (x, 0), TSI_SAME_STMT);
+      tsi_delink (&i);
+    }
+
   /* Resume execution after the exception.  Adding this now lets
      lower_eh_filter not add unnecessary gotos, as it is clear that
      we never fallthru from this copy of the finally block.  */
@@ -1708,8 +1726,10 @@ lower_eh_constructs (void)
   return 0;
 }
 
-struct tree_opt_pass pass_lower_eh =
+struct gimple_opt_pass pass_lower_eh =
 {
+ {
+  GIMPLE_PASS,
   "eh",                                        /* name */
   NULL,                                        /* gate */
   lower_eh_constructs,                 /* execute */
@@ -1721,8 +1741,8 @@ struct tree_opt_pass pass_lower_eh =
   PROP_gimple_leh,                     /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };
 
 \f
@@ -1877,7 +1897,10 @@ tree_could_trap_p (tree expr)
       || TREE_CODE_CLASS (code) == tcc_binary)
     {
       t = TREE_TYPE (expr);
-      fp_operation = FLOAT_TYPE_P (t);
+      if (COMPARISON_CLASS_P (expr))
+       fp_operation = FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0)));
+      else
+       fp_operation = FLOAT_TYPE_P (t);
       if (fp_operation)
        {
          honor_nans = flag_trapping_math && !flag_finite_math_only;
@@ -2157,23 +2180,17 @@ optimize_double_finally (tree one, tree two)
 
   if (same_handler_p (TREE_OPERAND (oneh, 1), TREE_OPERAND (two, 1)))
     {
-      tree twoh;
-
       tree b = TREE_OPERAND (oneh, 0);
       TREE_OPERAND (one, 1) = b;
       TREE_SET_CODE (one, TRY_CATCH_EXPR);
 
-      b = tsi_stmt (tsi_start (b));
-      twoh = TREE_OPERAND (two, 0);
-      /* same_handler_p only handles single-statement handlers,
-        so there must only be one statement.  */
-      i = tsi_start (twoh);
-      tsi_link_before (&i, unshare_expr (b), TSI_SAME_STMT);
+      i = tsi_start (TREE_OPERAND (two, 0));
+      tsi_link_before (&i, unsave_expr_now (b), TSI_SAME_STMT);
     }
 }
 
 /* Perform EH refactoring optimizations that are simpler to do when code
-   flow has been lowered but EH structurs haven't.  */
+   flow has been lowered but EH structures haven't.  */
 
 static void
 refactor_eh_r (tree t)
@@ -2233,8 +2250,10 @@ refactor_eh (void)
   return 0;
 }
 
-struct tree_opt_pass pass_refactor_eh =
+struct gimple_opt_pass pass_refactor_eh =
 {
+ {
+  GIMPLE_PASS,
   "ehopt",                             /* name */
   NULL,                                        /* gate */
   refactor_eh,                         /* execute */
@@ -2246,6 +2265,6 @@ struct tree_opt_pass pass_refactor_eh =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func,                      /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func                       /* todo_flags_finish */
+ }
 };