OSDN Git Service

PR target/21723
[pf3gnuchains/gcc-fork.git] / gcc / tree-eh.c
index 7d83746..76c7ef7 100644 (file)
@@ -15,8 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA.  */
 #include "timevar.h"
 #include "langhooks.h"
 #include "ggc.h"
+#include "toplev.h"
 
 \f
 /* Nonzero if we are using EH to handle cleanups.  */
@@ -1763,18 +1764,18 @@ mark_eh_edge (struct eh_region *region, void *data)
   e = find_edge (src, dst);
   if (!e)
     {
-      error ("EH edge %i->%i is missing %i %i.", src->index, dst->index, src, dst);
+      error ("EH edge %i->%i is missing", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else if (!(e->flags & EDGE_EH))
     {
-      error ("EH edge %i->%i miss EH flag.", src->index, dst->index);
+      error ("EH edge %i->%i miss EH flag", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else if (e->aux)
     {
       /* ??? might not be mistake.  */
-      error ("EH edge %i->%i has duplicated regions.", src->index, dst->index);
+      error ("EH edge %i->%i has duplicated regions", src->index, dst->index);
       mark_eh_edge_found_error = true;
     }
   else
@@ -1826,7 +1827,7 @@ verify_eh_edges (tree stmt)
     {
       if ((e->flags & EDGE_EH) && !e->aux)
        {
-         error ("Unnecesary EH edge %i->%i", bb->index, e->dest->index);
+         error ("unnecessary EH edge %i->%i", bb->index, e->dest->index);
          mark_eh_edge_found_error = true;
          return true;
        }
@@ -1868,6 +1869,13 @@ tree_could_trap_p (tree expr)
  restart:
   switch (code)
     {
+    case TARGET_MEM_REF:
+      /* For TARGET_MEM_REFs use the information based on the original
+        reference.  */
+      expr = TMR_ORIGINAL (expr);
+      code = TREE_CODE (expr);
+      goto restart;
+
     case COMPONENT_REF:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
@@ -2009,37 +2017,59 @@ bool
 tree_can_throw_internal (tree stmt)
 {
   int region_nr;
+  bool is_resx = false;
 
   if (TREE_CODE (stmt) == RESX_EXPR)
-    region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0));
+    region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0)), is_resx = true;
   else
     region_nr = lookup_stmt_eh_region (stmt);
   if (region_nr < 0)
     return false;
-  return can_throw_internal_1 (region_nr);
+  return can_throw_internal_1 (region_nr, is_resx);
 }
 
 bool
 tree_can_throw_external (tree stmt)
 {
   int region_nr;
+  bool is_resx = false;
 
   if (TREE_CODE (stmt) == RESX_EXPR)
-    region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0));
+    region_nr = TREE_INT_CST_LOW (TREE_OPERAND (stmt, 0)), is_resx = true;
   else
     region_nr = lookup_stmt_eh_region (stmt);
   if (region_nr < 0)
     return tree_could_throw_p (stmt);
   else
-    return can_throw_external_1 (region_nr);
+    return can_throw_external_1 (region_nr, is_resx);
 }
 
-bool
-maybe_clean_eh_stmt (tree stmt)
+/* Given a statement OLD_STMT and a new statement NEW_STMT that has replaced
+   OLD_STMT in the function, remove OLD_STMT from the EH table and put NEW_STMT
+   in the table if it should be in there.  Return TRUE if a replacement was
+   done that my require an EH edge purge.  */
+
+bool 
+maybe_clean_or_replace_eh_stmt (tree old_stmt, tree new_stmt) 
 {
-  if (!tree_could_throw_p (stmt))
-    if (remove_stmt_from_eh_region (stmt))
-      return true;
+  int region_nr = lookup_stmt_eh_region (old_stmt);
+
+  if (region_nr >= 0)
+    {
+      bool new_stmt_could_throw = tree_could_throw_p (new_stmt);
+
+      if (new_stmt == old_stmt && new_stmt_could_throw)
+       return false;
+
+      remove_stmt_from_eh_region (old_stmt);
+      if (new_stmt_could_throw)
+       {
+         add_stmt_to_eh_region (new_stmt, region_nr);
+         return false;
+       }
+      else
+       return true;
+    }
+
   return false;
 }
-