2 * sparse/check_signed.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * Check for things which are signed but probably should be unsigned.
13 * Hm... It seems like at this point in the processing, sparse makes all
14 * bitfields unsigned. Which is logical but not what GCC does.
22 #define VAR_ON_RIGHT 0
25 static void match_assign(struct expression
*expr
)
33 sym
= get_type(expr
->left
);
35 //sm_msg("could not get type");
38 if (sym
->bit_size
>= 32) /* max_val limits this */
40 if (!get_implied_value(expr
->right
, &val
))
44 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
45 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, max
, name
);
50 if (min
== 0 && val
== -1) /* assigning -1 to unsigned variables is idiomatic */
52 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
54 sm_msg("warn: assigning %lld to unsigned variable '%s'", val
, name
);
56 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, min
, name
);
62 static const char *get_tf(long long variable
, long long known
, int var_pos
, char op
)
64 if (op
== SPECIAL_EQUAL
)
66 if (op
== SPECIAL_NOTEQUAL
)
68 if (var_pos
== VAR_ON_LEFT
) {
69 if (variable
> known
&& (op
== '<' || op
== SPECIAL_LTE
))
71 if (variable
> known
&& (op
== '>' || op
== SPECIAL_GTE
))
73 if (variable
< known
&& (op
== '<' || op
== SPECIAL_LTE
))
75 if (variable
< known
&& (op
== '>' || op
== SPECIAL_GTE
))
78 if (var_pos
== VAR_ON_RIGHT
) {
79 if (known
> variable
&& (op
== '<' || op
== SPECIAL_LTE
))
81 if (known
> variable
&& (op
== '>' || op
== SPECIAL_GTE
))
83 if (known
< variable
&& (op
== '<' || op
== SPECIAL_LTE
))
85 if (known
< variable
&& (op
== '>' || op
== SPECIAL_GTE
))
91 static void match_condition(struct expression
*expr
)
94 struct expression
*var
= NULL
;
95 struct symbol
*type
= NULL
;
101 if (expr
->type
!= EXPR_COMPARE
)
104 if (get_value(expr
->left
, &known
)) {
107 } else if (get_value(expr
->right
, &known
)) {
114 type
= get_type(var
);
115 if (!type
|| type
->bit_size
>= 32)
118 max
= type_max(type
);
119 min
= type_min(type
);
121 name
= get_variable_from_expr_complex(var
, NULL
);
123 if (known
< 0 && type_unsigned(type
)) {
124 sm_msg("error: comparing unsigned '%s' to negative", name
);
129 if (!type_unsigned(type
))
131 if (lr
== VAR_ON_LEFT
) {
133 sm_msg("error: unsigned '%s' cannot be less than 0", name
);
134 if (expr
->op
== SPECIAL_LTE
)
135 sm_msg("warn: unsigned '%s' cannot be less than 0", name
);
137 if (lr
== VAR_ON_RIGHT
) {
139 sm_msg("error: unsigned '%s' cannot be less than 0", name
);
140 if (expr
->op
== SPECIAL_GTE
)
141 sm_msg("warn: unsigned '%s' cannot be less than 0", name
);
147 const char *tf
= get_tf(max
, known
, lr
, expr
->op
);
149 sm_msg("warn: %lld is more than %lld (max '%s' can be) so this is always %s.",
150 known
, max
, name
, tf
);
154 const char *tf
= get_tf(max
, known
, lr
, expr
->op
);
156 sm_msg("warn: %lld is less than %lld (min '%s' can be) so this is always %s.",
157 known
, min
, name
, tf
);
163 void check_signed(int id
)
167 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
168 add_hook(&match_condition
, CONDITION_HOOK
);