OSDN Git Service

PR c++/55877
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index d1ee63a..d56650d 100644 (file)
@@ -38,7 +38,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "except.h"
 #include "cfgloop.h"
 #include "cfglayout.h"
@@ -1570,7 +1569,7 @@ replace_uses_by (tree name, tree val)
          size_t i;
 
          fold_stmt_inplace (stmt);
-         if (cfgcleanup_altered_bbs)
+         if (cfgcleanup_altered_bbs && !is_gimple_debug (stmt))
            bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
 
          /* FIXME.  This should go in update_stmt.  */
@@ -2611,13 +2610,13 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       if (!POINTER_TYPE_P (TREE_TYPE (x))
          || !is_gimple_mem_ref_addr (x))
        {
-         error ("Invalid first operand of MEM_REF.");
+         error ("invalid first operand of MEM_REF");
          return x;
        }
       if (TREE_CODE (TREE_OPERAND (t, 1)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 1))))
        {
-         error ("Invalid offset operand of MEM_REF.");
+         error ("invalid offset operand of MEM_REF");
          return TREE_OPERAND (t, 1);
        }
       if (TREE_CODE (x) == ADDR_EXPR
@@ -2636,7 +2635,7 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
       break;
 
     case MODIFY_EXPR:
-      error ("MODIFY_EXPR not expected while having tuples.");
+      error ("MODIFY_EXPR not expected while having tuples");
       return *tp;
 
     case ADDR_EXPR:
@@ -2783,7 +2782,7 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
                                     TREE_TYPE (TREE_OPERAND (t, 1))))
        {
          error ("invalid operand to pointer plus, second operand is not an "
-                "integer with type of sizetype.");
+                "integer with type of sizetype");
          return t;
        }
       /* FALLTHROUGH */
@@ -2951,14 +2950,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
              && (TREE_CODE (op) == SSA_NAME
                  || is_gimple_min_invariant (op)))
            {
-             error ("Conversion of an SSA_NAME on the left hand side.");
+             error ("conversion of an SSA_NAME on the left hand side");
              debug_generic_stmt (expr);
              return true;
            }
          else if (TREE_CODE (op) == SSA_NAME
                   && TYPE_SIZE (TREE_TYPE (expr)) != TYPE_SIZE (TREE_TYPE (op)))
            {
-             error ("Conversion of register to a different size.");
+             error ("conversion of register to a different size");
              debug_generic_stmt (expr);
              return true;
            }
@@ -2973,14 +2972,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
     {
       if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)))
        {
-         error ("Invalid address operand in MEM_REF.");
+         error ("invalid address operand in MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
       if (TREE_CODE (TREE_OPERAND (expr, 1)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1))))
        {
-         error ("Invalid offset operand in MEM_REF.");
+         error ("invalid offset operand in MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
@@ -2990,14 +2989,14 @@ verify_types_in_gimple_reference (tree expr, bool require_lvalue)
       if (!TMR_BASE (expr)
          || !is_gimple_mem_ref_addr (TMR_BASE (expr)))
        {
-         error ("Invalid address operand in in TARGET_MEM_REF.");
+         error ("invalid address operand in in TARGET_MEM_REF");
          return true;
        }
       if (!TMR_OFFSET (expr)
          || TREE_CODE (TMR_OFFSET (expr)) != INTEGER_CST
          || !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr))))
        {
-         error ("Invalid offset operand in TARGET_MEM_REF.");
+         error ("invalid offset operand in TARGET_MEM_REF");
          debug_generic_stmt (expr);
          return true;
        }
@@ -3107,8 +3106,7 @@ verify_gimple_call (gimple stmt)
      call, and the decl should have DECL_STATIC_CHAIN set.  */
   if (gimple_call_chain (stmt))
     {
-      if (TREE_CODE (fn) != ADDR_EXPR
-         || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
+      if (!gimple_call_fndecl (stmt))
        {
          error ("static chain in indirect gimple call");
          return true;
@@ -3117,7 +3115,7 @@ verify_gimple_call (gimple stmt)
 
       if (!DECL_STATIC_CHAIN (fn))
        {
-         error ("static chain with function that doesn't use one");
+         error ("static chain with function that doesn%'t use one");
          return true;
        }
     }
@@ -3137,6 +3135,7 @@ verify_gimple_call (gimple stmt)
        {
          error ("invalid argument to gimple call");
          debug_generic_expr (arg);
+         return true;
        }
     }
 
@@ -3656,6 +3655,20 @@ verify_gimple_assign_ternary (gimple stmt)
        }
       break;
 
+    case FMA_EXPR:
+      if (!useless_type_conversion_p (lhs_type, rhs1_type)
+         || !useless_type_conversion_p (lhs_type, rhs2_type)
+         || !useless_type_conversion_p (lhs_type, rhs3_type))
+       {
+         error ("type mismatch in fused multiply-add expression");
+         debug_generic_expr (lhs_type);
+         debug_generic_expr (rhs1_type);
+         debug_generic_expr (rhs2_type);
+         debug_generic_expr (rhs3_type);
+         return true;
+       }
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -3698,7 +3711,13 @@ verify_gimple_assign_single (gimple stmt)
            return true;
          }
 
-       if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+       /* Technically there is no longer a need for matching types, but
+          gimple hygiene asks for this check.  In LTO we can end up
+          combining incompatible units and thus end up with addresses
+          of globals that change their type to a common one.  */
+       if (!in_lto_p
+           && !types_compatible_p (TREE_TYPE (op),
+                                   TREE_TYPE (TREE_TYPE (rhs1)))
            && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
                                                          TREE_TYPE (op)))
          {
@@ -3908,7 +3927,7 @@ verify_gimple_phi (gimple stmt)
 
   if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
     {
-      error ("Invalid PHI result");
+      error ("invalid PHI result");
       return true;
     }
 
@@ -3920,13 +3939,13 @@ verify_gimple_phi (gimple stmt)
          || (!is_gimple_reg (gimple_phi_result (stmt))
              && !is_gimple_addressable (arg)))
        {
-         error ("Invalid PHI argument");
+         error ("invalid PHI argument");
          debug_generic_stmt (arg);
          return true;
        }
       if (!useless_type_conversion_p (type, TREE_TYPE (arg)))
        {
-         error ("Incompatible types in PHI argument %u", i);
+         error ("incompatible types in PHI argument %u", i);
          debug_generic_stmt (type);
          debug_generic_stmt (TREE_TYPE (arg));
          return true;
@@ -4231,7 +4250,7 @@ verify_eh_throw_stmt_node (void **slot, void *data)
 
   if (!pointer_set_contains (visited, node->stmt))
     {
-      error ("Dead STMT in EH table");
+      error ("dead STMT in EH table");
       debug_gimple_stmt (node->stmt);
       eh_error_found = true;
     }
@@ -5098,6 +5117,7 @@ gimple_duplicate_bb (basic_block bb)
     {
       def_operand_p def_p;
       ssa_op_iter op_iter;
+      tree lhs;
 
       stmt = gsi_stmt (gsi);
       if (gimple_code (stmt) == GIMPLE_LABEL)
@@ -5111,6 +5131,24 @@ gimple_duplicate_bb (basic_block bb)
       maybe_duplicate_eh_stmt (copy, stmt);
       gimple_duplicate_stmt_histograms (cfun, copy, cfun, stmt);
 
+      /* When copying around a stmt writing into a local non-user
+        aggregate, make sure it won't share stack slot with other
+        vars.  */
+      lhs = gimple_get_lhs (stmt);
+      if (lhs && TREE_CODE (lhs) != SSA_NAME)
+       {
+         tree base = get_base_address (lhs);
+         if (base
+             && (TREE_CODE (base) == VAR_DECL
+                 || TREE_CODE (base) == RESULT_DECL)
+             && DECL_IGNORED_P (base)
+             && !TREE_STATIC (base)
+             && !DECL_EXTERNAL (base)
+             && (TREE_CODE (base) != VAR_DECL
+                 || !DECL_HAS_VALUE_EXPR_P (base)))
+           DECL_NONSHAREABLE (base) = 1;
+       }
+
       /* Create new names for all the definitions created by COPY and
         add replacement mappings for each new name.  */
       FOR_EACH_SSA_DEF_OPERAND (def_p, copy, op_iter, SSA_OP_ALL_DEFS)
@@ -6744,7 +6782,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
   if (check_last_block)
     {
       basic_block bb = EXIT_BLOCK_PTR->prev_bb;
-      gimple_stmt_iterator gsi = gsi_last_bb (bb);
+      gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
       gimple t = NULL;
 
       if (!gsi_end_p (gsi))
@@ -6778,7 +6816,7 @@ gimple_flow_call_edges_add (sbitmap blocks)
       if (blocks && !TEST_BIT (blocks, i))
        continue;
 
-      gsi = gsi_last_bb (bb);
+      gsi = gsi_last_nondebug_bb (bb);
       if (!gsi_end_p (gsi))
        {
          last_stmt = gsi_stmt (gsi);
@@ -6824,39 +6862,6 @@ gimple_flow_call_edges_add (sbitmap blocks)
   return blocks_split;
 }
 
-/* Purge dead abnormal call edges from basic block BB.  */
-
-bool
-gimple_purge_dead_abnormal_call_edges (basic_block bb)
-{
-  bool changed = gimple_purge_dead_eh_edges (bb);
-
-  if (cfun->has_nonlocal_label)
-    {
-      gimple stmt = last_stmt (bb);
-      edge_iterator ei;
-      edge e;
-
-      if (!(stmt && stmt_can_make_abnormal_goto (stmt)))
-       for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
-         {
-           if (e->flags & EDGE_ABNORMAL)
-             {
-               remove_edge (e);
-               changed = true;
-             }
-           else
-             ei_next (&ei);
-         }
-
-      /* See gimple_purge_dead_eh_edges below.  */
-      if (changed)
-       free_dominance_info (CDI_DOMINATORS);
-    }
-
-  return changed;
-}
-
 /* Removes edge E and all the blocks dominated by it, and updates dominance
    information.  The IL in E->src needs to be updated separately.
    If dominance info is not available, only the edge E is removed.*/
@@ -7010,6 +7015,8 @@ gimple_purge_dead_eh_edges (basic_block bb)
   return changed;
 }
 
+/* Purge dead EH edges from basic block listed in BLOCKS.  */
+
 bool
 gimple_purge_all_dead_eh_edges (const_bitmap blocks)
 {
@@ -7031,6 +7038,59 @@ gimple_purge_all_dead_eh_edges (const_bitmap blocks)
   return changed;
 }
 
+/* Purge dead abnormal call edges from basic block BB.  */
+
+bool
+gimple_purge_dead_abnormal_call_edges (basic_block bb)
+{
+  bool changed = false;
+  edge e;
+  edge_iterator ei;
+  gimple stmt = last_stmt (bb);
+
+  if (!cfun->has_nonlocal_label)
+    return false;
+
+  if (stmt && stmt_can_make_abnormal_goto (stmt))
+    return false;
+
+  for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
+    {
+      if (e->flags & EDGE_ABNORMAL)
+       {
+         remove_edge_and_dominated_blocks (e);
+         changed = true;
+       }
+      else
+       ei_next (&ei);
+    }
+
+  return changed;
+}
+
+/* Purge dead abnormal call edges from basic block listed in BLOCKS.  */
+
+bool
+gimple_purge_all_dead_abnormal_call_edges (const_bitmap blocks)
+{
+  bool changed = false;
+  unsigned i;
+  bitmap_iterator bi;
+
+  EXECUTE_IF_SET_IN_BITMAP (blocks, 0, i, bi)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+
+      /* Earlier gimple_purge_dead_abnormal_call_edges could have removed
+        this basic block already.  */
+      gcc_assert (bb || changed);
+      if (bb != NULL)
+       changed |= gimple_purge_dead_abnormal_call_edges (bb);
+    }
+
+  return changed;
+}
+
 /* This function is called whenever a new edge is created or
    redirected.  */
 
@@ -7137,7 +7197,7 @@ struct cfg_hooks gimple_cfg_hooks = {
   gimple_can_merge_blocks_p,   /* can_merge_blocks_p  */
   gimple_merge_blocks,         /* merge_blocks  */
   gimple_predict_edge,         /* predict_edge  */
-  gimple_predicted_by_p,               /* predicted_by_p  */
+  gimple_predicted_by_p,       /* predicted_by_p  */
   gimple_can_duplicate_bb_p,   /* can_duplicate_block_p  */
   gimple_duplicate_bb,         /* duplicate_block  */
   gimple_split_edge,           /* split_edge  */
@@ -7145,7 +7205,7 @@ struct cfg_hooks gimple_cfg_hooks = {
   NULL,                                /* tidy_fallthru_edge  */
   gimple_block_ends_with_call_p,/* block_ends_with_call_p */
   gimple_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
-  gimple_flow_call_edges_add,     /* flow_call_edges_add */
+  gimple_flow_call_edges_add,   /* flow_call_edges_add */
   gimple_execute_on_growing_pred,      /* execute_on_growing_pred */
   gimple_execute_on_shrinking_pred, /* execute_on_shrinking_pred */
   gimple_duplicate_loop_to_header_edge, /* duplicate loop for trees */