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 long long eqneq_max(struct symbol
*base_type
)
27 long long ret
= whole_range
.max
;
30 if (!base_type
|| !base_type
->bit_size
)
32 bits
= base_type
->bit_size
;
36 return type_max(base_type
);
41 static long long eqneq_min(struct symbol
*base_type
)
43 long long ret
= whole_range
.min
;
46 if (!base_type
|| !base_type
->bit_size
)
48 if (base_type
->bit_size
< 32)
49 return type_min(base_type
);
50 ret
= whole_range
.max
;
51 bits
= base_type
->bit_size
- 1;
56 static void match_assign(struct expression
*expr
)
64 if (expr
->op
== SPECIAL_AND_ASSIGN
|| expr
->op
== SPECIAL_OR_ASSIGN
)
67 sym
= get_type(expr
->left
);
69 //sm_msg("could not get type");
72 if (sym
->bit_size
>= 32) /* max_val limits this */
74 if (!get_implied_value(expr
->right
, &val
))
77 if (max
< val
&& !(val
< 256 && max
== 127)) {
78 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
79 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, max
, name
);
84 if (min
== 0 && val
== -1) /* assigning -1 to unsigned variables is idiomatic */
86 if (expr
->right
->type
== EXPR_PREOP
&& expr
->right
->op
== '~')
88 if (expr
->op
== SPECIAL_SUB_ASSIGN
|| expr
->op
== SPECIAL_ADD_ASSIGN
)
90 name
= get_variable_from_expr_complex(expr
->left
, NULL
);
92 sm_msg("warn: assigning %lld to unsigned variable '%s'", val
, name
);
94 sm_msg("warn: value %lld can't fit into %lld '%s'", val
, min
, name
);
100 static const char *get_tf(long long variable
, long long known
, int var_pos
, int op
)
102 if (op
== SPECIAL_EQUAL
)
104 if (op
== SPECIAL_NOTEQUAL
)
106 if (var_pos
== VAR_ON_LEFT
) {
107 if (variable
> known
&& (op
== '<' || op
== SPECIAL_LTE
))
109 if (variable
> known
&& (op
== '>' || op
== SPECIAL_GTE
))
111 if (variable
< known
&& (op
== '<' || op
== SPECIAL_LTE
))
113 if (variable
< known
&& (op
== '>' || op
== SPECIAL_GTE
))
116 if (var_pos
== VAR_ON_RIGHT
) {
117 if (known
> variable
&& (op
== '<' || op
== SPECIAL_LTE
))
119 if (known
> variable
&& (op
== '>' || op
== SPECIAL_GTE
))
121 if (known
< variable
&& (op
== '<' || op
== SPECIAL_LTE
))
123 if (known
< variable
&& (op
== '>' || op
== SPECIAL_GTE
))
129 static void match_condition(struct expression
*expr
)
132 struct expression
*var
= NULL
;
133 struct symbol
*var_type
= NULL
;
134 struct symbol
*known_type
= NULL
;
140 if (expr
->type
!= EXPR_COMPARE
)
143 if (get_value(expr
->left
, &known
)) {
144 if (get_value(expr
->right
, &max
))
145 return; /* both sides known */
148 known_type
= get_type(expr
->left
);
149 } else if (get_value(expr
->right
, &known
)) {
152 known_type
= get_type(expr
->right
);
157 var_type
= get_type(var
);
160 if (var_type
->bit_size
>= 32 && !option_spammy
)
163 name
= get_variable_from_expr_complex(var
, NULL
);
165 if (expr
->op
== SPECIAL_EQUAL
|| expr
->op
== SPECIAL_NOTEQUAL
) {
166 if (eqneq_max(var_type
) < known
|| eqneq_min(var_type
) > known
)
167 sm_msg("error: %s is never equal to %lld (wrong type %lld - %lld).",
168 name
, known
, eqneq_min(var_type
), eqneq_max(var_type
));
172 max
= type_max(var_type
);
173 min
= type_min(var_type
);
176 const char *tf
= get_tf(max
, known
, lr
, expr
->op
);
178 sm_msg("warn: %lld is more than %lld (max '%s' can be) so this is always %s.",
179 known
, max
, name
, tf
);
182 if (known
== 0 && type_unsigned(var_type
)) {
183 if ((lr
&& expr
->op
== '<') || (!lr
&& expr
->op
== '>'))
184 sm_msg("warn: unsigned '%s' is never less than zero.", name
);
188 if (type_unsigned(var_type
) && known_type
&& !type_unsigned(known_type
) && known
< 0) {
189 sm_msg("warn: unsigned '%s' is never less than zero (%lld).", name
, known
);
193 if (min
< 0 && min
> known
) {
194 const char *tf
= get_tf(min
, known
, lr
, expr
->op
);
196 sm_msg("warn: %lld is less than %lld (min '%s' can be) so this is always %s.",
197 known
, min
, name
, tf
);
203 void check_signed(int id
)
207 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
208 add_hook(&match_condition
, CONDITION_HOOK
);