math: revert accidentally committed code
[smatch.git] / check_signed.c
blob39c67503ec533036737e97acd5f7cb9ce16a1c17
1 /*
2 * sparse/check_signed.c
4 * Copyright (C) 2009 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
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.
18 #include "smatch.h"
19 #include "smatch_extra.h"
21 static int my_id;
23 #define VAR_ON_RIGHT 0
24 #define VAR_ON_LEFT 1
26 static void match_assign(struct expression *expr)
28 struct symbol *sym;
29 sval_t sval;
30 sval_t max;
31 sval_t min;
32 char *left_name, *right_name;
34 if (expr->op == SPECIAL_AND_ASSIGN || expr->op == SPECIAL_OR_ASSIGN)
35 return;
37 sym = get_type(expr->left);
38 if (!sym) {
39 //sm_msg("could not get type");
40 return;
42 if (sym->bit_size < 0 || sym->bit_size >= 32) /* max_val limits this */
43 return;
44 if (!get_implied_value(expr->right, &sval))
45 return;
46 max = sval_type_max(sym);
47 if (sym != &bool_ctype && sval_cmp(max, sval) < 0 &&
48 !(sval.value < 256 && max.value == 127)) {
49 left_name = expr_to_str(expr->left);
50 right_name = expr_to_str(expr->right);
51 sm_msg("warn: '%s' %s can't fit into %s '%s'",
52 right_name, sval_to_numstr(sval), sval_to_numstr(max), left_name);
53 free_string(left_name);
55 min = sval_type_min(sym);
56 if (sval_cmp_t(&llong_ctype, min, sval) > 0) {
57 if (min.value == 0 && sval.value == -1) /* assigning -1 to unsigned variables is idiomatic */
58 return;
59 if (expr->right->type == EXPR_PREOP && expr->right->op == '~')
60 return;
61 if (expr->op == SPECIAL_SUB_ASSIGN || expr->op == SPECIAL_ADD_ASSIGN)
62 return;
63 if (sval_positive_bits(sval) == 7)
64 return;
65 left_name = expr_to_str(expr->left);
66 if (min.value == 0) {
67 sm_msg("warn: assigning %s to unsigned variable '%s'",
68 sval_to_str(sval), left_name);
69 } else {
70 sm_msg("warn: value %s can't fit into %s '%s'",
71 sval_to_str(sval), sval_to_str(min), left_name);
73 free_string(left_name);
77 static int cap_gt_zero_and_lt(struct expression *expr)
80 struct expression *var = expr->left;
81 struct expression *tmp;
82 char *name1 = NULL;
83 char *name2 = NULL;
84 sval_t known;
85 int ret = 0;
86 int i;
88 if (!get_value(expr->right, &known) || known.value != 0)
89 return 0;
91 i = 0;
92 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
93 if (!i++)
94 continue;
95 if (tmp->op == SPECIAL_LOGICAL_AND) {
96 struct expression *right = strip_expr(tmp->right);
98 if (right->op != '<' &&
99 right->op != SPECIAL_UNSIGNED_LT &&
100 right->op != SPECIAL_LTE &&
101 right->op != SPECIAL_UNSIGNED_LTE)
102 return 0;
104 name1 = expr_to_str(var);
105 if (!name1)
106 goto free;
108 name2 = expr_to_str(right->left);
109 if (!name2)
110 goto free;
111 if (!strcmp(name1, name2))
112 ret = 1;
113 goto free;
116 return 0;
117 } END_FOR_EACH_PTR_REVERSE(tmp);
119 free:
120 free_string(name1);
121 free_string(name2);
122 return ret;
125 static int cap_lt_zero_or_gt(struct expression *expr)
128 struct expression *var = expr->left;
129 struct expression *tmp;
130 char *name1 = NULL;
131 char *name2 = NULL;
132 sval_t known;
133 int ret = 0;
134 int i;
136 if (!get_value(expr->right, &known) || known.value != 0)
137 return 0;
139 i = 0;
140 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
141 if (!i++)
142 continue;
143 if (tmp->op == SPECIAL_LOGICAL_OR) {
144 struct expression *right = strip_expr(tmp->right);
146 if (right->op != '>' &&
147 right->op != SPECIAL_UNSIGNED_GT &&
148 right->op != SPECIAL_GTE &&
149 right->op != SPECIAL_UNSIGNED_GTE)
150 return 0;
152 name1 = expr_to_str(var);
153 if (!name1)
154 goto free;
156 name2 = expr_to_str(right->left);
157 if (!name2)
158 goto free;
159 if (!strcmp(name1, name2))
160 ret = 1;
161 goto free;
164 return 0;
165 } END_FOR_EACH_PTR_REVERSE(tmp);
167 free:
168 free_string(name1);
169 free_string(name2);
170 return ret;
173 static int cap_both_sides(struct expression *expr)
175 switch (expr->op) {
176 case '<':
177 case SPECIAL_UNSIGNED_LT:
178 case SPECIAL_LTE:
179 case SPECIAL_UNSIGNED_LTE:
180 return cap_lt_zero_or_gt(expr);
181 case '>':
182 case SPECIAL_UNSIGNED_GT:
183 case SPECIAL_GTE:
184 case SPECIAL_UNSIGNED_GTE:
185 return cap_gt_zero_and_lt(expr);
187 return 0;
190 static int compare_against_macro(struct expression *expr)
192 sval_t known;
194 if (expr->op != SPECIAL_UNSIGNED_LT)
195 return 0;
197 if (!get_value(expr->right, &known) || known.value != 0)
198 return 0;
199 return !!get_macro_name(expr->right->pos);
202 static int print_unsigned_never_less_than_zero(struct expression *expr)
204 sval_t known;
205 char *name;
207 if (expr->op != SPECIAL_UNSIGNED_LT)
208 return 0;
210 if (!get_value(expr->right, &known) || known.value != 0)
211 return 0;
213 name = expr_to_str(expr->left);
214 sm_msg("warn: unsigned '%s' is never less than zero.", name);
215 free_string(name);
216 return 1;
219 static void match_condition(struct expression *expr)
221 struct symbol *type;
222 sval_t known;
223 sval_t min, max;
224 struct range_list *rl_left_orig, *rl_right_orig;
225 struct range_list *rl_left, *rl_right;
227 if (expr->type != EXPR_COMPARE)
228 return;
230 type = get_type(expr);
231 if (!type)
232 return;
234 /* screw it. I am writing this to mark yoda code as buggy.
235 * Valid comparisons between an unsigned and zero are:
236 * 1) inside a macro.
237 * 2) foo < LOWER_BOUND where LOWER_BOUND is a macro.
238 * 3) foo < 0 || foo > X in exactly this format. No Yoda.
239 * 4) foo >= 0 && foo < X
241 if (get_macro_name(expr->pos))
242 return;
243 if (compare_against_macro(expr))
244 return;
245 if (cap_both_sides(expr))
246 return;
248 /* This is a special case for the common error */
249 if (print_unsigned_never_less_than_zero(expr))
250 return;
252 /* check that one and only one side is known */
253 if (get_value(expr->left, &known)) {
254 if (get_value(expr->right, &known))
255 return;
256 rl_left_orig = alloc_rl(known, known);
257 rl_left = cast_rl(type, rl_left_orig);
259 min = sval_type_min(get_type(expr->right));
260 max = sval_type_max(get_type(expr->right));
261 rl_right_orig = alloc_rl(min, max);
262 rl_right = cast_rl(type, rl_right_orig);
263 } else if (get_value(expr->right, &known)) {
264 rl_right_orig = alloc_rl(known, known);
265 rl_right = cast_rl(type, rl_right_orig);
267 min = sval_type_min(get_type(expr->left));
268 max = sval_type_max(get_type(expr->left));
269 rl_left_orig = alloc_rl(min, max);
270 rl_left = cast_rl(type, rl_left_orig);
271 } else {
272 return;
275 if (!possibly_true_rl(rl_left, expr->op, rl_right)) {
276 char *name = expr_to_str(expr);
278 sm_msg("warn: impossible condition '(%s) => (%s %s %s)'", name,
279 show_rl(rl_left), show_special(expr->op),
280 show_rl(rl_right));
281 free_string(name);
284 if (!possibly_false_rl(rl_left, expr->op, rl_right)) {
285 char *name = expr_to_str(expr);
287 sm_msg("warn: always true condition '(%s) => (%s %s %s)'", name,
288 show_rl(rl_left_orig), show_special(expr->op),
289 show_rl(rl_right_orig));
290 free_string(name);
294 void check_signed(int id)
296 my_id = id;
298 add_hook(&match_assign, ASSIGNMENT_HOOK);
299 add_hook(&match_condition, CONDITION_HOOK);