summaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-09 19:21:18 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2008-09-09 19:21:18 +0000
commit45cb67c919f95074341164e3a2e350732e78d373 (patch)
tree7ce00b243f903b7dbfb65abea5f7d07041368f2a /gcc/tree-cfg.c
parent534783cff20b859b0a7edcab38eca01f0d0e1993 (diff)
downloadgcc-45cb67c919f95074341164e3a2e350732e78d373.tar.gz
2008-09-08 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r140164 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@140169 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r--gcc/tree-cfg.c311
1 files changed, 178 insertions, 133 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index ce06d0e583d..4b253bf7899 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3168,67 +3168,94 @@ valid_fixed_convert_types_p (tree type1, tree type2)
|| FIXED_POINT_TYPE_P (type2)));
}
-/* Verify that OP is a valid GIMPLE operand. Return true if there is
- an error, false otherwise. */
-
-static bool
-verify_types_in_gimple_op (tree op)
-{
- if (!is_gimple_val (op) && !is_gimple_lvalue (op))
- {
- error ("Invalid GIMPLE operand");
- debug_generic_expr (op);
- return true;
- }
-
- return false;
-}
-
-
/* Verify the contents of a GIMPLE_CALL STMT. Returns true when there
is a problem, otherwise false. */
static bool
-verify_types_in_gimple_call (gimple stmt)
+verify_gimple_call (gimple stmt)
{
- bool failed = false;
- unsigned int i;
- tree fn;
+ tree fn = gimple_call_fn (stmt);
+ tree fntype;
- if (gimple_call_lhs (stmt))
- failed |= verify_types_in_gimple_op (gimple_call_lhs (stmt));
+ if (!POINTER_TYPE_P (TREE_TYPE (fn))
+ || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) != METHOD_TYPE))
+ {
+ error ("non-function in gimple call");
+ return true;
+ }
- fn = gimple_call_fn (stmt);
- if (TREE_CODE (fn) != OBJ_TYPE_REF
- && verify_types_in_gimple_op (fn))
- failed = true;
+ if (gimple_call_lhs (stmt)
+ && !is_gimple_lvalue (gimple_call_lhs (stmt)))
+ {
+ error ("invalid LHS in gimple call");
+ return true;
+ }
- if (gimple_call_chain (stmt))
- failed |= verify_types_in_gimple_op (gimple_call_chain (stmt));
+ fntype = TREE_TYPE (TREE_TYPE (fn));
+ if (gimple_call_lhs (stmt)
+ && !useless_type_conversion_p (TREE_TYPE (gimple_call_lhs (stmt)),
+ TREE_TYPE (fntype))
+ /* ??? At least C++ misses conversions at assignments from
+ void * call results.
+ ??? Java is completely off. Especially with functions
+ returning java.lang.Object.
+ For now simply allow arbitrary pointer type conversions. */
+ && !(POINTER_TYPE_P (TREE_TYPE (gimple_call_lhs (stmt)))
+ && POINTER_TYPE_P (TREE_TYPE (fntype))))
+ {
+ error ("invalid conversion in gimple call");
+ debug_generic_stmt (TREE_TYPE (gimple_call_lhs (stmt)));
+ debug_generic_stmt (TREE_TYPE (fntype));
+ return true;
+ }
- for (i = 0; i < gimple_call_num_args (stmt); i++)
- failed |= verify_types_in_gimple_op (gimple_call_arg (stmt,i));
+ /* ??? 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
+ unit-at-a-time we have a chance to fix this. */
- return failed;
+ return false;
}
-
-/* Verify the contents of a GIMPLE_COND STMT. Returns true when there
- is a problem, otherwise false. */
+/* Verifies the gimple comparison with the result type TYPE and
+ the operands OP0 and OP1. */
static bool
-verify_types_in_gimple_cond (gimple stmt)
+verify_gimple_comparison (tree type, tree op0, tree op1)
{
- bool failed = false;
-
- failed |= verify_types_in_gimple_op (gimple_cond_lhs (stmt));
- failed |= verify_types_in_gimple_op (gimple_cond_rhs (stmt));
- failed |= verify_types_in_gimple_op (gimple_cond_true_label (stmt));
- failed |= verify_types_in_gimple_op (gimple_cond_false_label (stmt));
+ tree op0_type = TREE_TYPE (op0);
+ tree op1_type = TREE_TYPE (op1);
- return failed;
-}
+ if (!is_gimple_val (op0) || !is_gimple_val (op1))
+ {
+ error ("invalid operands in gimple comparison");
+ return true;
+ }
+ /* For comparisons we do not have the operations type as the
+ effective type the comparison is carried out in. Instead
+ we require that either the first operand is trivially
+ convertible into the second, or the other way around.
+ The resulting type of a comparison may be any integral type.
+ Because we special-case pointers to void we allow
+ comparisons of pointers with the same mode as well. */
+ if ((!useless_type_conversion_p (op0_type, op1_type)
+ && !useless_type_conversion_p (op1_type, op0_type)
+ && (!POINTER_TYPE_P (op0_type)
+ || !POINTER_TYPE_P (op1_type)
+ || TYPE_MODE (op0_type) != TYPE_MODE (op1_type)))
+ || !INTEGRAL_TYPE_P (type))
+ {
+ error ("type mismatch in comparison expression");
+ debug_generic_expr (type);
+ debug_generic_expr (op0_type);
+ debug_generic_expr (op1_type);
+ return true;
+ }
+
+ return false;
+}
/* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there
is a problem, otherwise false.
@@ -3588,35 +3615,7 @@ verify_types_in_gimple_assign (gimple stmt)
return verify_types_in_gimple_reference (rhs1);
case tcc_comparison:
- {
- if (!is_gimple_val (rhs1) || !is_gimple_val (rhs2))
- {
- error ("invalid operands in comparison expression");
- return true;
- }
-
- /* For comparisons we do not have the operations type as the
- effective type the comparison is carried out in. Instead
- we require that either the first operand is trivially
- convertible into the second, or the other way around.
- The resulting type of a comparison may be any integral type.
- Because we special-case pointers to void we allow
- comparisons of pointers with the same mode as well. */
- if ((!useless_type_conversion_p (rhs1_type, rhs2_type)
- && !useless_type_conversion_p (rhs2_type, rhs1_type)
- && (!POINTER_TYPE_P (rhs1_type)
- || !POINTER_TYPE_P (rhs2_type)
- || TYPE_MODE (rhs1_type) != TYPE_MODE (rhs2_type)))
- || !INTEGRAL_TYPE_P (lhs_type))
- {
- error ("type mismatch in comparison expression");
- debug_generic_expr (lhs_type);
- debug_generic_expr (rhs1_type);
- debug_generic_expr (rhs2_type);
- return true;
- }
- break;
- }
+ return verify_gimple_comparison (lhs_type, rhs1, rhs2);
default:;
}
@@ -3629,27 +3628,72 @@ verify_types_in_gimple_assign (gimple stmt)
is a problem, otherwise false. */
static bool
-verify_types_in_gimple_return (gimple stmt)
+verify_gimple_return (gimple stmt)
{
tree op = gimple_return_retval (stmt);
+ tree restype = TREE_TYPE (TREE_TYPE (cfun->decl));
+ /* We cannot test for present return values as we do not fix up missing
+ return values from the original source. */
if (op == NULL)
return false;
-
- return verify_types_in_gimple_op (op);
+
+ if (!is_gimple_val (op)
+ && TREE_CODE (op) != RESULT_DECL)
+ {
+ error ("invalid operand in return statement");
+ debug_generic_stmt (op);
+ return true;
+ }
+
+ if (!useless_type_conversion_p (restype, TREE_TYPE (op))
+ /* ??? With C++ we can have the situation that the result
+ decl is a reference type while the return type is an aggregate. */
+ && !(TREE_CODE (op) == RESULT_DECL
+ && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE
+ && useless_type_conversion_p (restype, TREE_TYPE (TREE_TYPE (op)))))
+ {
+ error ("invalid conversion in return statement");
+ debug_generic_stmt (restype);
+ debug_generic_stmt (TREE_TYPE (op));
+ return true;
+ }
+
+ return false;
}
+/* Verify the contents of a GIMPLE_GOTO STMT. Returns true when there
+ is a problem, otherwise false. */
+
+static bool
+verify_gimple_goto (gimple stmt)
+{
+ tree dest = gimple_goto_dest (stmt);
+
+ /* ??? We have two canonical forms of direct goto destinations, a
+ bare LABEL_DECL and an ADDR_EXPR of a LABEL_DECL. */
+ if (TREE_CODE (dest) != LABEL_DECL
+ && (!is_gimple_val (dest)
+ || !POINTER_TYPE_P (TREE_TYPE (dest))))
+ {
+ error ("goto destination is neither a label nor a pointer");
+ return true;
+ }
+
+ return false;
+}
+
/* Verify the contents of a GIMPLE_SWITCH STMT. Returns true when there
is a problem, otherwise false. */
static bool
-verify_types_in_gimple_switch (gimple stmt)
+verify_gimple_switch (gimple stmt)
{
if (!is_gimple_val (gimple_switch_index (stmt)))
{
error ("invalid operand to switch statement");
- debug_generic_expr (gimple_switch_index (stmt));
+ debug_generic_stmt (gimple_switch_index (stmt));
return true;
}
@@ -3661,16 +3705,34 @@ verify_types_in_gimple_switch (gimple stmt)
and false otherwise. */
static bool
-verify_types_in_gimple_phi (gimple stmt)
+verify_gimple_phi (gimple stmt)
{
- size_t i;
+ tree type = TREE_TYPE (gimple_phi_result (stmt));
+ unsigned i;
- if (verify_types_in_gimple_op (gimple_phi_result (stmt)))
- return true;
+ if (!is_gimple_variable (gimple_phi_result (stmt)))
+ {
+ error ("Invalid PHI result");
+ return true;
+ }
for (i = 0; i < gimple_phi_num_args (stmt); i++)
- if (verify_types_in_gimple_op (gimple_phi_arg_def (stmt, i)))
- return true;
+ {
+ tree arg = gimple_phi_arg_def (stmt, i);
+ if (!is_gimple_val (arg))
+ {
+ 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");
+ debug_generic_stmt (type);
+ debug_generic_stmt (TREE_TYPE (arg));
+ return true;
+ }
+ }
return false;
}
@@ -3702,32 +3764,37 @@ verify_types_in_gimple_stmt (gimple stmt)
return TREE_CODE (gimple_label_label (stmt)) != LABEL_DECL;
case GIMPLE_CALL:
- return verify_types_in_gimple_call (stmt);
+ return verify_gimple_call (stmt);
case GIMPLE_COND:
- return verify_types_in_gimple_cond (stmt);
+ return verify_gimple_comparison (boolean_type_node,
+ gimple_cond_lhs (stmt),
+ gimple_cond_rhs (stmt));
case GIMPLE_GOTO:
- return verify_types_in_gimple_op (gimple_goto_dest (stmt));
-
- case GIMPLE_NOP:
- case GIMPLE_PREDICT:
- return false;
+ return verify_gimple_goto (stmt);
case GIMPLE_SWITCH:
- return verify_types_in_gimple_switch (stmt);
+ return verify_gimple_switch (stmt);
case GIMPLE_RETURN:
- return verify_types_in_gimple_return (stmt);
+ return verify_gimple_return (stmt);
case GIMPLE_ASM:
return false;
case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return verify_types_in_gimple_op (gimple_cdt_location (stmt));
+ return (!is_gimple_reg (gimple_cdt_location (stmt))
+ || !POINTER_TYPE_P (TREE_TYPE (gimple_cdt_location (stmt))));
case GIMPLE_PHI:
- return verify_types_in_gimple_phi (stmt);
+ return verify_gimple_phi (stmt);
+
+ /* Tuples that do not have tree operands. */
+ case GIMPLE_NOP:
+ case GIMPLE_RESX:
+ case GIMPLE_PREDICT:
+ return false;
default:
gcc_unreachable ();
@@ -3748,44 +3815,22 @@ verify_types_in_gimple_seq_2 (gimple_seq stmts)
switch (gimple_code (stmt))
{
- case GIMPLE_BIND:
- err |= verify_types_in_gimple_seq_2 (gimple_bind_body (stmt));
- break;
-
- case GIMPLE_TRY:
- err |= verify_types_in_gimple_seq_2 (gimple_try_eval (stmt));
- err |= verify_types_in_gimple_seq_2 (gimple_try_cleanup (stmt));
- break;
-
- case GIMPLE_EH_FILTER:
- err |= verify_types_in_gimple_seq_2
- (gimple_eh_filter_failure (stmt));
- break;
-
- case GIMPLE_CATCH:
- err |= verify_types_in_gimple_seq_2 (gimple_catch_handler (stmt));
- break;
-
- case GIMPLE_OMP_CRITICAL:
- case GIMPLE_OMP_CONTINUE:
- case GIMPLE_OMP_MASTER:
- case GIMPLE_OMP_ORDERED:
- case GIMPLE_OMP_SECTION:
- case GIMPLE_OMP_FOR:
- case GIMPLE_OMP_PARALLEL:
- case GIMPLE_OMP_TASK:
- case GIMPLE_OMP_SECTIONS:
- case GIMPLE_OMP_SINGLE:
- case GIMPLE_OMP_ATOMIC_STORE:
- case GIMPLE_OMP_ATOMIC_LOAD:
- break;
-
- /* Tuples that do not have trees. */
- case GIMPLE_NOP:
- case GIMPLE_RESX:
- case GIMPLE_OMP_RETURN:
- case GIMPLE_PREDICT:
- break;
+ case GIMPLE_BIND:
+ err |= verify_types_in_gimple_seq_2 (gimple_bind_body (stmt));
+ break;
+
+ case GIMPLE_TRY:
+ err |= verify_types_in_gimple_seq_2 (gimple_try_eval (stmt));
+ err |= verify_types_in_gimple_seq_2 (gimple_try_cleanup (stmt));
+ break;
+
+ case GIMPLE_EH_FILTER:
+ err |= verify_types_in_gimple_seq_2 (gimple_eh_filter_failure (stmt));
+ break;
+
+ case GIMPLE_CATCH:
+ err |= verify_types_in_gimple_seq_2 (gimple_catch_handler (stmt));
+ break;
default:
{