OSDN Git Service

PR debug/41276
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfg.c
index 8470d76..02daee0 100644 (file)
@@ -476,11 +476,12 @@ fold_cond_expr_cond (void)
 
       if (stmt && gimple_code (stmt) == GIMPLE_COND)
        {
+         location_t loc = gimple_location (stmt);
          tree cond;
          bool zerop, onep;
 
          fold_defer_overflow_warnings ();
-         cond = fold_binary (gimple_cond_code (stmt), boolean_type_node,
+         cond = fold_binary_loc (loc, gimple_cond_code (stmt), boolean_type_node,
                              gimple_cond_lhs (stmt), gimple_cond_rhs (stmt));
          if (cond)
            {
@@ -755,13 +756,15 @@ same_line_p (location_t locus1, location_t locus2)
 static void
 assign_discriminator (location_t locus, basic_block bb)
 {
-  gimple to_stmt;
+  gimple first_in_to_bb, last_in_to_bb;
 
   if (locus == 0 || bb->discriminator != 0)
     return;
 
-  to_stmt = first_non_label_stmt (bb);
-  if (to_stmt && same_line_p (locus, gimple_location (to_stmt)))
+  first_in_to_bb = first_non_label_stmt (bb);
+  last_in_to_bb = last_stmt (bb);
+  if ((first_in_to_bb && same_line_p (locus, gimple_location (first_in_to_bb)))
+      || (last_in_to_bb && same_line_p (locus, gimple_location (last_in_to_bb))))
     bb->discriminator = next_discriminator_for_locus (locus);
 }
 
@@ -1351,6 +1354,24 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
       && DECL_NONLOCAL (gimple_label_label (stmt)))
     return false;
 
+  /* Examine the labels at the beginning of B.  */
+  for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      tree lab;
+      stmt = gsi_stmt (gsi);
+      if (gimple_code (stmt) != GIMPLE_LABEL)
+       break;
+      lab = gimple_label_label (stmt);
+
+      /* Do not remove user labels.  */
+      if (!DECL_ARTIFICIAL (lab))
+       return false;
+    }
+
+  /* Protect the loop latches.  */
+  if (current_loops && b->loop_father->latch == b)
+    return false;
+
   /* It must be possible to eliminate all phi nodes in B.  If ssa form
      is not up-to-date, we cannot eliminate any phis; however, if only
      some symbols as whole are marked for renaming, this is not a problem,
@@ -1374,24 +1395,52 @@ gimple_can_merge_blocks_p (basic_block a, basic_block b)
        }
     }
 
-  /* Do not remove user labels.  */
-  for (gsi = gsi_start_bb (b); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      stmt = gsi_stmt (gsi);
-      if (gimple_code (stmt) != GIMPLE_LABEL)
-       break;
-      if (!DECL_ARTIFICIAL (gimple_label_label (stmt)))
-       return false;
-    }
+  return true;
+}
 
-  /* Protect the loop latches.  */
-  if (current_loops
-      && b->loop_father->latch == b)
-    return false;
+/* Return true if the var whose chain of uses starts at PTR has no
+   nondebug uses.  */
+bool
+has_zero_uses_1 (const ssa_use_operand_t *head)
+{
+  const ssa_use_operand_t *ptr;
+
+  for (ptr = head->next; ptr != head; ptr = ptr->next)
+    if (!is_gimple_debug (USE_STMT (ptr)))
+      return false;
 
   return true;
 }
 
+/* Return true if the var whose chain of uses starts at PTR has a
+   single nondebug use.  Set USE_P and STMT to that single nondebug
+   use, if so, or to NULL otherwise.  */
+bool
+single_imm_use_1 (const ssa_use_operand_t *head,
+                 use_operand_p *use_p, gimple *stmt)
+{
+  ssa_use_operand_t *ptr, *single_use = 0;
+
+  for (ptr = head->next; ptr != head; ptr = ptr->next)
+    if (!is_gimple_debug (USE_STMT (ptr)))
+      {
+       if (single_use)
+         {
+           single_use = NULL;
+           break;
+         }
+       single_use = ptr;
+      }
+
+  if (use_p)
+    *use_p = single_use;
+
+  if (stmt)
+    *stmt = single_use ? single_use->loc.stmt : NULL;
+
+  return !!single_use;
+}
+
 /* Replaces all uses of NAME by VAL.  */
 
 void
@@ -1638,12 +1687,14 @@ remove_useless_stmts_warn_notreached (gimple_seq stmts)
     {
       gimple stmt = gsi_stmt (gsi);
 
+      if (gimple_no_warning_p (stmt)) return false;
+
       if (gimple_has_location (stmt))
         {
           location_t loc = gimple_location (stmt);
           if (LOCATION_LINE (loc) > 0)
            {
-              warning (OPT_Wunreachable_code, "%Hwill never be executed", &loc);
+              warning_at (loc, OPT_Wunreachable_code, "will never be executed");
               return true;
             }
         }
@@ -2258,7 +2309,11 @@ remove_bb (basic_block bb)
   /* Remove all the instructions in the block.  */
   if (bb_seq (bb) != NULL)
     {
-      for (i = gsi_start_bb (bb); !gsi_end_p (i);)
+      /* Walk backwards so as to get a chance to substitute all
+        released DEFs into debug stmts.  See
+        eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+        details.  */
+      for (i = gsi_last_bb (bb); !gsi_end_p (i);)
        {
          gimple stmt = gsi_stmt (i);
          if (gimple_code (stmt) == GIMPLE_LABEL
@@ -2294,13 +2349,17 @@ remove_bb (basic_block bb)
              gsi_remove (&i, true);
            }
 
+         if (gsi_end_p (i))
+           i = gsi_last_bb (bb);
+         else
+           gsi_prev (&i);
+
          /* Don't warn for removed gotos.  Gotos are often removed due to
             jump threading, thus resulting in bogus warnings.  Not great,
             since this way we lose warnings for gotos in the original
             program that are indeed unreachable.  */
          if (gimple_code (stmt) != GIMPLE_GOTO
-             && gimple_has_location (stmt)
-             && !loc)
+             && gimple_has_location (stmt))
            loc = gimple_location (stmt);
        }
     }
@@ -2310,7 +2369,7 @@ remove_bb (basic_block bb)
      loop above, so the last statement we process is the first statement
      in the block.  */
   if (loc > BUILTINS_LOCATION && LOCATION_LINE (loc) > 0)
-    warning (OPT_Wunreachable_code, "%Hwill never be executed", &loc);
+    warning_at (loc, OPT_Wunreachable_code, "will never be executed");
 
   remove_phi_nodes_and_edges_for_unreachable_block (bb);
   bb->il.gimple = NULL;
@@ -2676,11 +2735,17 @@ gimple_cfg2vcg (FILE *file)
 bool
 is_ctrl_stmt (gimple t)
 {
-  return gimple_code (t) == GIMPLE_COND
-    || gimple_code (t) == GIMPLE_SWITCH
-    || gimple_code (t) == GIMPLE_GOTO
-    || gimple_code (t) == GIMPLE_RETURN
-    || gimple_code (t) == GIMPLE_RESX;
+  switch (gimple_code (t))
+    {
+    case GIMPLE_COND:
+    case GIMPLE_SWITCH:
+    case GIMPLE_GOTO:
+    case GIMPLE_RETURN:
+    case GIMPLE_RESX:
+      return true;
+    default:
+      return false;
+    }
 }
 
 
@@ -2692,24 +2757,30 @@ is_ctrl_altering_stmt (gimple t)
 {
   gcc_assert (t);
 
-  if (is_gimple_call (t))
+  switch (gimple_code (t))
     {
-      int flags = gimple_call_flags (t);
+    case GIMPLE_CALL:
+      {
+       int flags = gimple_call_flags (t);
 
-      /* A non-pure/const call alters flow control if the current
-        function has nonlocal labels.  */
-      if (!(flags & (ECF_CONST | ECF_PURE))
-         && cfun->has_nonlocal_label)
-       return true;
+       /* A non-pure/const call alters flow control if the current
+          function has nonlocal labels.  */
+       if (!(flags & (ECF_CONST | ECF_PURE)) && cfun->has_nonlocal_label)
+         return true;
 
-      /* A call also alters control flow if it does not return.  */
-      if (gimple_call_flags (t) & ECF_NORETURN)
-       return true;
-    }
+       /* A call also alters control flow if it does not return.  */
+       if (gimple_call_flags (t) & ECF_NORETURN)
+         return true;
+      }
+      break;
 
-  /* OpenMP directives alter control flow.  */
-  if (is_gimple_omp (t))
-    return true;
+    CASE_GIMPLE_OMP:
+      /* OpenMP directives alter control flow.  */
+      return true;
+
+    default:
+      break;
+    }
 
   /* If a statement can throw, it alters control flow.  */
   return stmt_can_throw_internal (t);
@@ -2802,7 +2873,14 @@ gimple
 first_stmt (basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start_bb (bb);
-  return !gsi_end_p (i) ? gsi_stmt (i) : NULL;
+  gimple stmt = NULL;
+
+  while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+    {
+      gsi_next (&i);
+      stmt = NULL;
+    }
+  return stmt;
 }
 
 /* Return the first non-label statement in basic block BB.  */
@@ -2821,8 +2899,15 @@ first_non_label_stmt (basic_block bb)
 gimple
 last_stmt (basic_block bb)
 {
-  gimple_stmt_iterator b = gsi_last_bb (bb);
-  return !gsi_end_p (b) ? gsi_stmt (b) : NULL;
+  gimple_stmt_iterator i = gsi_last_bb (bb);
+  gimple stmt = NULL;
+
+  while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i))))
+    {
+      gsi_prev (&i);
+      stmt = NULL;
+    }
+  return stmt;
 }
 
 /* Return the last statement of an otherwise empty block.  Return NULL
@@ -2832,14 +2917,14 @@ last_stmt (basic_block bb)
 gimple
 last_and_only_stmt (basic_block bb)
 {
-  gimple_stmt_iterator i = gsi_last_bb (bb);
+  gimple_stmt_iterator i = gsi_last_nondebug_bb (bb);
   gimple last, prev;
 
   if (gsi_end_p (i))
     return NULL;
 
   last = gsi_stmt (i);
-  gsi_prev (&i);
+  gsi_prev_nondebug (&i);
   if (gsi_end_p (i))
     return last;
 
@@ -2881,7 +2966,7 @@ reinstall_phi_args (edge new_edge, edge old_edge)
  
       gcc_assert (result == gimple_phi_result (phi));
   
-      add_phi_arg (phi, arg, new_edge);
+      add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm));
     }
   
   redirect_edge_var_map_clear (old_edge);
@@ -2896,11 +2981,15 @@ static basic_block
 split_edge_bb_loc (edge edge_in)
 {
   basic_block dest = edge_in->dest;
+  basic_block dest_prev = dest->prev_bb;
 
-  if (dest->prev_bb && find_edge (dest->prev_bb, dest))
-    return edge_in->src;
-  else
-    return dest->prev_bb;
+  if (dest_prev)
+    {
+      edge e = find_edge (dest_prev, dest);
+      if (e && !(e->flags & EDGE_COMPLEX))
+       return edge_in->src;
+    }
+  return dest_prev;
 }
 
 /* Split a (typically critical) edge EDGE_IN.  Return the new block.
@@ -3884,12 +3973,13 @@ verify_gimple_assign_single (gimple stmt)
            return true;
          }
 
-       if (!one_pointer_to_useless_type_conversion_p (lhs_type,
-                                                      TREE_TYPE (op)))
+       if (!types_compatible_p (TREE_TYPE (op), TREE_TYPE (TREE_TYPE (rhs1)))
+           && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1),
+                                                         TREE_TYPE (op)))
          {
            error ("type mismatch in address expression");
-           debug_generic_stmt (lhs_type);
-           debug_generic_stmt (TYPE_POINTER_TO (TREE_TYPE (op)));
+           debug_generic_stmt (TREE_TYPE (rhs1));
+           debug_generic_stmt (TREE_TYPE (op));
            return true;
          }
 
@@ -4072,7 +4162,7 @@ verify_gimple_phi (gimple stmt)
   tree type = TREE_TYPE (gimple_phi_result (stmt));
   unsigned i;
 
-  if (!is_gimple_variable (gimple_phi_result (stmt)))
+  if (TREE_CODE (gimple_phi_result (stmt)) != SSA_NAME)
     {
       error ("Invalid PHI result");
       return true;
@@ -4103,23 +4193,28 @@ verify_gimple_phi (gimple stmt)
 }
 
 
+/* Verify a gimple debug statement STMT.
+   Returns true if anything is wrong.  */
+
+static bool
+verify_gimple_debug (gimple stmt ATTRIBUTE_UNUSED)
+{
+  /* There isn't much that could be wrong in a gimple debug stmt.  A
+     gimple debug bind stmt, for example, maps a tree, that's usually
+     a VAR_DECL or a PARM_DECL, but that could also be some scalarized
+     component or member of an aggregate type, to another tree, that
+     can be an arbitrary expression.  These stmts expand into debug
+     insns, and are converted to debug notes by var-tracking.c.  */
+  return false;
+}
+
+
 /* Verify the GIMPLE statement STMT.  Returns true if there is an
    error, otherwise false.  */
 
 static bool
 verify_types_in_gimple_stmt (gimple stmt)
 {
-  if (is_gimple_omp (stmt))
-    {
-      /* OpenMP directives are validated by the FE and never operated
-        on by the optimizers.  Furthermore, GIMPLE_OMP_FOR may contain
-        non-gimple expressions when the main index variable has had
-        its address taken.  This does not affect the loop itself
-        because the header of an GIMPLE_OMP_FOR is merely used to determine
-        how to setup the parallel iteration.  */
-      return false;
-    }
-
   switch (gimple_code (stmt))
     {
     case GIMPLE_ASSIGN:
@@ -4157,6 +4252,18 @@ verify_types_in_gimple_stmt (gimple stmt)
     case GIMPLE_PREDICT:
       return false;
 
+    CASE_GIMPLE_OMP:
+      /* OpenMP directives are validated by the FE and never operated
+        on by the optimizers.  Furthermore, GIMPLE_OMP_FOR may contain
+        non-gimple expressions when the main index variable has had
+        its address taken.  This does not affect the loop itself
+        because the header of an GIMPLE_OMP_FOR is merely used to determine
+        how to setup the parallel iteration.  */
+      return false;
+
+    case GIMPLE_DEBUG:
+      return verify_gimple_debug (stmt);
+
     default:
       gcc_unreachable ();
     }
@@ -4263,6 +4370,9 @@ verify_stmt (gimple_stmt_iterator *gsi)
        }
     }
 
+  if (is_gimple_debug (stmt))
+    return false;
+
   memset (&wi, 0, sizeof (wi));
   addr = walk_gimple_op (gsi_stmt (*gsi), verify_expr, &wi);
   if (addr)
@@ -4835,7 +4945,8 @@ gimple_make_forwarder_block (edge fallthru)
       new_phi = create_phi_node (var, bb);
       SSA_NAME_DEF_STMT (var) = new_phi;
       gimple_phi_set_result (phi, make_ssa_name (SSA_NAME_VAR (var), phi));
-      add_phi_arg (new_phi, gimple_phi_result (phi), fallthru);
+      add_phi_arg (new_phi, gimple_phi_result (phi), fallthru, 
+                  UNKNOWN_LOCATION);
     }
 
   /* Add the arguments we have stored on edges.  */
@@ -4934,20 +5045,23 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
   if (e->flags & EDGE_ABNORMAL)
     return NULL;
 
-  if (e->src != ENTRY_BLOCK_PTR
-      && (ret = gimple_try_redirect_by_replacing_jump (e, dest)))
-    return ret;
-
   if (e->dest == dest)
     return NULL;
 
   if (e->flags & EDGE_EH)
     return redirect_eh_edge (e, dest);
 
+  if (e->src != ENTRY_BLOCK_PTR)
+    {
+      ret = gimple_try_redirect_by_replacing_jump (e, dest);
+      if (ret)
+       return ret;
+    }
+
   gsi = gsi_last_bb (bb);
   stmt = gsi_end_p (gsi) ? NULL : gsi_stmt (gsi);
 
-  switch (stmt ? gimple_code (stmt) : ERROR_MARK)
+  switch (stmt ? gimple_code (stmt) : GIMPLE_ERROR_MARK)
     {
     case GIMPLE_COND:
       /* For COND_EXPR, we only need to redirect the edge.  */
@@ -5234,7 +5348,8 @@ add_phi_args_after_copy_edge (edge e_copy)
       phi = gsi_stmt (psi);
       phi_copy = gsi_stmt (psi_copy);
       def = PHI_ARG_DEF_FROM_EDGE (phi, e);
-      add_phi_arg (phi_copy, def, e_copy);
+      add_phi_arg (phi_copy, def, e_copy, 
+                  gimple_phi_arg_location_from_edge (phi, e));
     }
 }
 
@@ -6327,7 +6442,7 @@ dump_function_to_file (tree fn, FILE *file, int flags)
     print_node (file, "", fn, 2);
 
   dsf = DECL_STRUCT_FUNCTION (fn);
-  if (dsf && (flags & TDF_DETAILS))
+  if (dsf && (flags & TDF_EH))
     dump_eh_tree (file, dsf);
 
   if (flags & TDF_RAW && !gimple_has_body_p (fn))
@@ -6610,7 +6725,7 @@ debug_loop_num (unsigned num, int verbosity)
 static bool
 gimple_block_ends_with_call_p (basic_block bb)
 {
-  gimple_stmt_iterator gsi = gsi_last_bb (bb);
+  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
   return is_gimple_call (gsi_stmt (gsi));
 }
 
@@ -6916,8 +7031,12 @@ remove_edge_and_dominated_blocks (edge e)
     remove_edge (e);
   else
     {
-      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
-       delete_basic_block (bb);
+      /* Walk backwards so as to get a chance to substitute all
+        released DEFs into debug stmts.  See
+        eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+        details.  */
+      for (i = VEC_length (basic_block, bbs_to_remove); i-- > 0; )
+       delete_basic_block (VEC_index (basic_block, bbs_to_remove, i));
     }
 
   /* Update the dominance information.  The immediate dominator may change only
@@ -7053,7 +7172,7 @@ gimple_lv_adjust_loop_header_phi (basic_block first, basic_block second,
       phi1 = gsi_stmt (psi1);
       phi2 = gsi_stmt (psi2);
       def = PHI_ARG_DEF (phi2, e2->dest_idx);
-      add_phi_arg (phi1, def, e);
+      add_phi_arg (phi1, def, e, gimple_phi_arg_location_from_edge (phi2, e2));
     }
 }
 
@@ -7147,7 +7266,7 @@ split_critical_edges (void)
             Go ahead and split them too.  This matches the logic in
             gimple_find_edge_insert_loc.  */
          else if ((!single_pred_p (e->dest)
-                   || phi_nodes (e->dest)
+                   || !gimple_seq_empty_p (phi_nodes (e->dest))
                    || e->dest == EXIT_BLOCK_PTR)
                   && e->src != ENTRY_BLOCK_PTR
                   && !(e->flags & EDGE_ABNORMAL))
@@ -7194,8 +7313,9 @@ gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
                 tree type, tree a, tree b, tree c)
 {
   tree ret;
+  location_t loc = gimple_location (gsi_stmt (*gsi));
 
-  ret = fold_build3 (code, type, a, b, c);
+  ret = fold_build3_loc (loc, code, type, a, b, c);
   STRIP_NOPS (ret);
 
   return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
@@ -7211,7 +7331,7 @@ gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
 {
   tree ret;
 
-  ret = fold_build2 (code, type, a, b);
+  ret = fold_build2_loc (gimple_location (gsi_stmt (*gsi)), code, type, a, b);
   STRIP_NOPS (ret);
 
   return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
@@ -7227,7 +7347,7 @@ gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
 {
   tree ret;
 
-  ret = fold_build1 (code, type, a);
+  ret = fold_build1_loc (gimple_location (gsi_stmt (*gsi)), code, type, a);
   STRIP_NOPS (ret);
 
   return force_gimple_operand_gsi (gsi, ret, true, NULL, true,
@@ -7260,7 +7380,7 @@ execute_warn_function_return (void)
        }
       if (location == UNKNOWN_LOCATION)
        location = cfun->function_end_locus;
-      warning (0, "%H%<noreturn%> function does return", &location);
+      warning_at (location, 0, "%<noreturn%> function does return");
     }
 
   /* If we see "return;" in some basic block, then we do reach the end
@@ -7342,9 +7462,9 @@ execute_warn_function_noreturn (void)
       && !TREE_THIS_VOLATILE (cfun->decl)
       && EDGE_COUNT (EXIT_BLOCK_PTR->preds) == 0
       && !lang_hooks.missing_noreturn_ok_p (cfun->decl))
-    warning (OPT_Wmissing_noreturn, "%Jfunction might be possible candidate "
-            "for attribute %<noreturn%>",
-            cfun->decl);
+    warning_at (DECL_SOURCE_LOCATION (cfun->decl), OPT_Wmissing_noreturn,
+               "function might be possible candidate "
+               "for attribute %<noreturn%>");
   return 0;
 }
 
@@ -7366,3 +7486,100 @@ struct gimple_opt_pass pass_warn_function_noreturn =
   0                                    /* todo_flags_finish */
  }
 };
+
+
+/* Walk a gimplified function and warn for functions whose return value is
+   ignored and attribute((warn_unused_result)) is set.  This is done before
+   inlining, so we don't have to worry about that.  */
+
+static void
+do_warn_unused_result (gimple_seq seq)
+{
+  tree fdecl, ftype;
+  gimple_stmt_iterator i;
+
+  for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
+    {
+      gimple g = gsi_stmt (i);
+
+      switch (gimple_code (g))
+       {
+       case GIMPLE_BIND:
+         do_warn_unused_result (gimple_bind_body (g));
+         break;
+       case GIMPLE_TRY:
+         do_warn_unused_result (gimple_try_eval (g));
+         do_warn_unused_result (gimple_try_cleanup (g));
+         break;
+       case GIMPLE_CATCH:
+         do_warn_unused_result (gimple_catch_handler (g));
+         break;
+       case GIMPLE_EH_FILTER:
+         do_warn_unused_result (gimple_eh_filter_failure (g));
+         break;
+
+       case GIMPLE_CALL:
+         if (gimple_call_lhs (g))
+           break;
+
+         /* This is a naked call, as opposed to a GIMPLE_CALL with an
+            LHS.  All calls whose value is ignored should be
+            represented like this.  Look for the attribute.  */
+         fdecl = gimple_call_fndecl (g);
+         ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
+
+         if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+           {
+             location_t loc = gimple_location (g);
+
+             if (fdecl)
+               warning_at (loc, OPT_Wunused_result,
+                           "ignoring return value of %qD, "
+                           "declared with attribute warn_unused_result",
+                           fdecl);
+             else
+               warning_at (loc, OPT_Wunused_result,
+                           "ignoring return value of function "
+                           "declared with attribute warn_unused_result");
+           }
+         break;
+
+       default:
+         /* Not a container, not a call, or a call whose value is used.  */
+         break;
+       }
+    }
+}
+
+static unsigned int
+run_warn_unused_result (void)
+{
+  do_warn_unused_result (gimple_body (current_function_decl));
+  return 0;
+}
+
+static bool
+gate_warn_unused_result (void)
+{
+  return flag_warn_unused_result;
+}
+
+struct gimple_opt_pass pass_warn_unused_result =
+{
+  {
+    GIMPLE_PASS,
+    "*warn_unused_result",             /* name */
+    gate_warn_unused_result,           /* gate */
+    run_warn_unused_result,            /* execute */
+    NULL,                              /* sub */
+    NULL,                              /* next */
+    0,                                 /* static_pass_number */
+    TV_NONE,                           /* tv_id */
+    PROP_gimple_any,                   /* properties_required */
+    0,                                 /* properties_provided */
+    0,                                 /* properties_destroyed */
+    0,                                 /* todo_flags_start */
+    0,                                 /* todo_flags_finish */
+  }
+};
+