/* Control flow functions for trees.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>
This file is part of GCC.
remove_bb (basic_block bb)
{
gimple_stmt_iterator i;
- source_location loc = UNKNOWN_LOCATION;
if (dump_file)
{
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_location (stmt);
}
}
- /* If requested, give a warning that the first statement in the
- block is unreachable. We walk statements backwards in the
- loop above, so the last statement we process is the first statement
- in the block. */
- if (loc > BUILTINS_LOCATION && LOCATION_LINE (loc) > 0)
- warning_at (loc, OPT_Wunreachable_code, "will never be executed");
-
remove_phi_nodes_and_edges_for_unreachable_block (bb);
bb->il.gimple = NULL;
}
return true;
/* A call also alters control flow if it does not return. */
- if (gimple_call_flags (t) & ECF_NORETURN)
+ if (flags & ECF_NORETURN)
return true;
}
break;
{
tree fn = gimple_call_fn (stmt);
tree fntype;
+ unsigned i;
+
+ if (TREE_CODE (fn) != OBJ_TYPE_REF
+ && !is_gimple_val (fn))
+ {
+ error ("invalid function in gimple call");
+ debug_generic_stmt (fn);
+ return true;
+ }
if (!POINTER_TYPE_P (TREE_TYPE (fn))
|| (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
return true;
}
+ if (gimple_call_lhs (stmt) && gimple_call_noreturn_p (stmt))
+ {
+ error ("LHS in noreturn call");
+ return true;
+ }
+
fntype = TREE_TYPE (TREE_TYPE (fn));
if (gimple_call_lhs (stmt)
&& !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
return true;
}
+ if (gimple_call_chain (stmt)
+ && !is_gimple_val (gimple_call_chain (stmt)))
+ {
+ error ("invalid static chain in gimple call");
+ debug_generic_stmt (gimple_call_chain (stmt));
+ return true;
+ }
+
/* If there is a static chain argument, this should not be an indirect
call, and the decl should have DECL_STATIC_CHAIN set. */
if (gimple_call_chain (stmt))
/* ??? The C frontend passes unpromoted arguments in case it
didn't see a function declaration before the call. So for now
- leave the call arguments unverified. Once we gimplify
+ leave the call arguments mostly unverified. Once we gimplify
unit-at-a-time we have a chance to fix this. */
+ for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ {
+ tree arg = gimple_call_arg (stmt, i);
+ if (!is_gimple_operand (arg))
+ {
+ error ("invalid argument to gimple call");
+ debug_generic_expr (arg);
+ }
+ }
+
return false;
}
return verify_gimple_call (stmt);
case GIMPLE_COND:
+ if (TREE_CODE_CLASS (gimple_cond_code (stmt)) != tcc_comparison)
+ {
+ error ("invalid comparison code in gimple cond");
+ return true;
+ }
+ if (!(!gimple_cond_true_label (stmt)
+ || TREE_CODE (gimple_cond_true_label (stmt)) == LABEL_DECL)
+ || !(!gimple_cond_false_label (stmt)
+ || TREE_CODE (gimple_cond_false_label (stmt)) == LABEL_DECL))
+ {
+ error ("invalid labels in gimple cond");
+ return true;
+ }
+
return verify_gimple_comparison (boolean_type_node,
gimple_cond_lhs (stmt),
gimple_cond_rhs (stmt));
err = 1;
}
+ if (prev_stmt && EH_LANDING_PAD_NR (label) != 0)
+ {
+ error ("EH landing pad label ");
+ print_generic_expr (stderr, label, 0);
+ fprintf (stderr, " is not first in a sequence of labels in bb %d",
+ bb->index);
+ err = 1;
+ }
+
if (label_to_block (label) != bb)
{
error ("label ");
{
basic_block bb = e->dest;
- if (phi_nodes (bb))
+ if (!gimple_seq_empty_p (phi_nodes (bb)))
reserve_phi_args_for_new_edge (bb);
}
static void
gimple_execute_on_shrinking_pred (edge e)
{
- if (phi_nodes (e->dest))
+ if (!gimple_seq_empty_p (phi_nodes (e->dest)))
remove_phi_args (e);
}