smatch_extra: foo = !!x; does not modify x.
[smatch.git] / smatch_extra.c
blob9b463528f30ade45b0054f1da0c2ea24fe9548be
1 /*
2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
11 * smatch_extra.c is supposed to track the value of every variable.
14 #include <stdlib.h>
15 #ifndef __USE_ISOC99
16 #define __USE_ISOC99
17 #endif
18 #include <limits.h>
19 #include "parse.h"
20 #include "smatch.h"
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
24 static int my_id;
26 static struct symbol *cur_func;
28 struct data_range whole_range = {
29 .min = LLONG_MIN,
30 .max = LLONG_MAX,
33 static struct smatch_state *alloc_extra_state_empty(void)
35 struct smatch_state *state;
36 struct data_info *dinfo;
38 dinfo = __alloc_data_info(0);
39 dinfo->type = DATA_RANGE;
40 dinfo->value_ranges = NULL;
41 state = __alloc_smatch_state(0);
42 state->data = dinfo;
43 return state;
46 static struct smatch_state *alloc_extra_state_no_name(int val)
48 struct smatch_state *state;
50 state = __alloc_smatch_state(0);
51 state->data = (void *)alloc_dinfo_range(val, val);
52 return state;
55 /* We do this because ->value_ranges is a list */
56 struct smatch_state *extra_undefined(void)
58 struct data_info *dinfo;
59 static struct smatch_state *ret;
60 static struct symbol *prev_func;
62 if (prev_func == cur_func)
63 return ret;
64 prev_func = cur_func;
66 dinfo = alloc_dinfo_range(whole_range.min, whole_range.max);
67 ret = __alloc_smatch_state(0);
68 ret->name = "unknown";
69 ret->data = dinfo;
70 return ret;
73 struct smatch_state *alloc_extra_state(int val)
75 struct smatch_state *state;
77 state = alloc_extra_state_no_name(val);
78 state->name = show_ranges(get_dinfo(state)->value_ranges);
79 return state;
82 struct smatch_state *alloc_extra_state_range(long long min, long long max)
84 struct smatch_state *state;
86 if (min == whole_range.min && max == whole_range.max)
87 return extra_undefined();
88 state = __alloc_smatch_state(0);
89 state->data = (void *)alloc_dinfo_range(min, max);
90 state->name = show_ranges(get_dinfo(state)->value_ranges);
91 return state;
94 struct smatch_state *alloc_extra_state_range_list(struct range_list *rl)
96 struct smatch_state *state;
98 state = __alloc_smatch_state(0);
99 state->data = (void *)alloc_dinfo_range_list(rl);
100 state->name = show_ranges(get_dinfo(state)->value_ranges);
101 return state;
104 struct data_info *get_dinfo(struct smatch_state *state)
106 if (!state)
107 return NULL;
108 return (struct data_info *)state->data;
112 struct smatch_state *filter_range(struct smatch_state *orig,
113 long long filter_min, long long filter_max)
115 struct smatch_state *ret;
116 struct data_info *orig_info;
117 struct data_info *ret_info;
119 if (!orig)
120 orig = extra_undefined();
121 orig_info = get_dinfo(orig);
122 ret = alloc_extra_state_empty();
123 ret_info = get_dinfo(ret);
124 ret_info->value_ranges = remove_range(orig_info->value_ranges, filter_min, filter_max);
125 ret->name = show_ranges(ret_info->value_ranges);
126 return ret;
129 struct smatch_state *add_filter(struct smatch_state *orig, long long num)
131 return filter_range(orig, num, num);
134 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
135 struct smatch_state *s1,
136 struct smatch_state *s2)
138 struct data_info *info1 = get_dinfo(s1);
139 struct data_info *info2 = get_dinfo(s2);
140 struct data_info *ret_info;
141 struct smatch_state *tmp;
142 struct range_list *value_ranges;
144 value_ranges = range_list_union(info1->value_ranges, info2->value_ranges);
145 tmp = alloc_extra_state_empty();
146 ret_info = get_dinfo(tmp);
147 ret_info->value_ranges = value_ranges;
148 tmp->name = show_ranges(ret_info->value_ranges);
149 return tmp;
152 struct sm_state *__extra_pre_loop_hook_before(struct statement *iterator_pre_statement)
154 struct expression *expr;
155 char *name;
156 struct symbol *sym;
157 struct sm_state *ret = NULL;
159 if (!iterator_pre_statement)
160 return NULL;
161 if (iterator_pre_statement->type != STMT_EXPRESSION)
162 return NULL;
163 expr = iterator_pre_statement->expression;
164 if (expr->type != EXPR_ASSIGNMENT)
165 return NULL;
166 name = get_variable_from_expr(expr->left, &sym);
167 if (!name || !sym)
168 goto free;
169 ret = get_sm_state(my_id, name, sym);
170 free:
171 free_string(name);
172 return ret;
175 int __iterator_unchanged(struct sm_state *sm, struct statement *iterator)
177 struct expression *iter_expr;
178 char *name;
179 struct symbol *sym;
180 int ret = 0;
182 if (!iterator)
183 return 0;
184 if (iterator->type != STMT_EXPRESSION)
185 return 0;
186 iter_expr = iterator->expression;
187 if (iter_expr->op != SPECIAL_INCREMENT && iter_expr->op != SPECIAL_DECREMENT)
188 return 0;
189 name = get_variable_from_expr(iter_expr->unop, &sym);
190 if (!name || !sym)
191 goto free;
192 if (get_sm_state(my_id, name, sym) == sm)
193 ret = 1;
194 free:
195 free_string(name);
196 return ret;
199 void __extra_pre_loop_hook_after(struct sm_state *sm,
200 struct statement *iterator,
201 struct expression *condition)
203 struct expression *iter_expr;
204 char *name;
205 struct symbol *sym;
206 long long value;
207 int left = 0;
208 struct smatch_state *state;
209 struct data_info *dinfo;
210 long long min, max;
212 iter_expr = iterator->expression;
214 if (condition->type != EXPR_COMPARE)
215 return;
216 if (!get_value(condition->left, &value)) {
217 if (!get_value(condition->right, &value))
218 return;
219 left = 1;
221 if (left)
222 name = get_variable_from_expr(condition->left, &sym);
223 else
224 name = get_variable_from_expr(condition->right, &sym);
225 if (!name || !sym)
226 goto free;
227 if (sym != sm->sym || strcmp(name, sm->name))
228 goto free;
229 state = get_state(my_id, name, sym);
230 dinfo = get_dinfo(state);
231 min = get_dinfo_min(dinfo);
232 max = get_dinfo_max(dinfo);
233 if (iter_expr->op == SPECIAL_INCREMENT && min != whole_range.min && max == whole_range.max) {
234 set_state(my_id, name, sym, alloc_extra_state(min));
235 } else if (min == whole_range.min && max != whole_range.max) {
236 set_state(my_id, name, sym, alloc_extra_state(max));
238 free:
239 free_string(name);
240 return;
243 static struct smatch_state *unmatched_state(struct sm_state *sm)
245 return extra_undefined();
248 static void match_function_call(struct expression *expr)
250 struct expression *tmp;
251 struct symbol *sym;
252 char *name;
253 int i = 0;
255 FOR_EACH_PTR(expr->args, tmp) {
256 if (tmp->type == EXPR_PREOP && tmp->op == '&') {
257 name = get_variable_from_expr(tmp->unop, &sym);
258 if (name) {
259 set_state(my_id, name, sym, extra_undefined());
261 free_string(name);
263 i++;
264 } END_FOR_EACH_PTR(tmp);
267 static void match_assign(struct expression *expr)
269 struct expression *left;
270 struct expression *right;
271 struct symbol *sym;
272 char *name;
273 long long value;
274 int known;
275 long long min = whole_range.min;
276 long long max = whole_range.max;
277 long long tmp;
278 struct range_list *rl = NULL;
280 left = strip_expr(expr->left);
281 name = get_variable_from_expr(left, &sym);
282 if (!name)
283 return;
284 right = strip_expr(expr->right);
285 while (right->type == EXPR_ASSIGNMENT && right->op == '=')
286 right = strip_expr(right->left);
288 known = get_implied_range_list(right, &rl);
289 if (expr->op == '=') {
290 if (known)
291 set_state(my_id, name, sym, alloc_extra_state_range_list(rl));
292 else
293 set_state(my_id, name, sym, extra_undefined());
294 goto free;
297 known = get_implied_value(right, &value);
298 if (expr->op == SPECIAL_ADD_ASSIGN) {
299 if (get_implied_min(left, &tmp)) {
300 if (known)
301 min = tmp + value;
302 else
303 min = tmp;
307 if (expr->op == SPECIAL_SUB_ASSIGN) {
308 if (get_implied_max(left, &tmp)) {
309 if (known)
310 max = tmp - value;
311 else
312 max = tmp;
316 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
317 free:
318 free_string(name);
321 static void unop_expr(struct expression *expr)
323 struct symbol *sym;
324 char *name;
325 long long min = whole_range.min;
326 long long max = whole_range.max;
327 long long val;
329 if (expr->op == '*')
330 return;
331 if (expr->op == '(')
332 return;
333 if (expr->op == '!')
334 return;
336 name = get_variable_from_expr(expr->unop, &sym);
337 if (!name)
338 goto free;
339 if (expr->op == SPECIAL_INCREMENT) {
340 if (get_implied_min(expr->unop, &val))
341 min = val + 1;
343 if (expr->op == SPECIAL_DECREMENT) {
344 if (get_implied_max(expr->unop, &val))
345 max = val - 1;
347 set_state(my_id, name, sym, alloc_extra_state_range(min, max));
348 free:
349 free_string(name);
352 static void match_declarations(struct symbol *sym)
354 const char *name;
355 long long val;
357 if (sym->ident) {
358 name = sym->ident->name;
359 if (sym->initializer) {
360 if (get_value(sym->initializer, &val))
361 set_state(my_id, name, sym, alloc_extra_state(val));
362 else
363 set_state(my_id, name, sym, extra_undefined());
364 scoped_state(my_id, name, sym);
365 } else {
366 set_state(my_id, name, sym, extra_undefined());
367 scoped_state(my_id, name, sym);
372 static void match_function_def(struct symbol *sym)
374 struct symbol *arg;
376 cur_func = sym;
377 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
378 if (!arg->ident) {
379 continue;
381 set_state(my_id, arg->ident->name, arg, extra_undefined());
382 } END_FOR_EACH_PTR(arg);
385 #define VAL_SINGLE 0
386 #define VAL_MAX 1
387 #define VAL_MIN 2
389 static int get_implied_value_helper(struct expression *expr, long long *val, int what)
391 struct smatch_state *state;
392 struct symbol *sym;
393 char *name;
395 if (get_value(expr, val))
396 return 1;
398 name = get_variable_from_expr(expr, &sym);
399 if (!name)
400 return 0;
401 state = get_state(my_id, name, sym);
402 free_string(name);
403 if (!state || !state->data)
404 return 0;
405 if (what == VAL_SINGLE)
406 return get_single_value_from_range(get_dinfo(state), val);
407 if (what == VAL_MAX) {
408 *val = get_dinfo_max(get_dinfo(state));
409 if (*val == whole_range.max) /* this means just guessing */
410 return 0;
411 return 1;
413 *val = get_dinfo_min(get_dinfo(state));
414 if (*val == whole_range.min)
415 return 0;
416 return 1;
419 int get_implied_single_val(struct expression *expr, long long *val)
421 return get_implied_value_helper(expr, val, VAL_SINGLE);
424 int get_implied_max(struct expression *expr, long long *val)
426 return get_implied_value_helper(expr, val, VAL_MAX);
429 int get_implied_min(struct expression *expr, long long *val)
431 return get_implied_value_helper(expr, val, VAL_MIN);
434 int get_implied_single_fuzzy_max(struct expression *expr, long long *max)
436 struct sm_state *sm;
437 struct sm_state *tmp;
439 if (get_implied_max(expr, max))
440 return 1;
442 sm = get_sm_state_expr(SMATCH_EXTRA, expr);
443 if (!sm)
444 return 0;
446 *max = whole_range.min;
447 FOR_EACH_PTR(sm->possible, tmp) {
448 long long new_min;
450 new_min = get_dinfo_min(get_dinfo(tmp->state));
451 if (new_min > *max)
452 *max = new_min;
453 } END_FOR_EACH_PTR(tmp);
455 if (*max > whole_range.min)
456 return 1;
457 return 0;
460 static int last_stmt_val(struct statement *stmt, long long *val)
462 struct expression *expr;
464 if (!stmt)
465 return 0;
467 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
468 if (stmt->type != STMT_EXPRESSION)
469 return 0;
470 expr = stmt->expression;
471 return get_value(expr, val);
474 static void match_comparison(struct expression *expr)
476 long long fixed;
477 char *name = NULL;
478 struct symbol *sym;
479 struct smatch_state *one_state;
480 struct smatch_state *two_state;
481 struct smatch_state *orig;
482 int left = 0;
483 int comparison = expr->op;
484 struct expression *varies = expr->right;
486 if (!get_value(expr->left, &fixed)) {
487 if (!get_value(expr->right, &fixed))
488 return;
489 varies = expr->left;
490 left = 1;
492 if (varies->op == SPECIAL_INCREMENT || varies->op == SPECIAL_DECREMENT)
493 varies = varies->unop;
494 if (varies->type == EXPR_CALL) {
495 function_comparison(comparison, varies, fixed, left);
496 return;
499 name = get_variable_from_expr(varies, &sym);
500 if (!name || !sym)
501 goto free;
503 orig = get_state(my_id, name, sym);
504 if (!orig)
505 orig = extra_undefined();
507 switch (comparison) {
508 case '<':
509 case SPECIAL_UNSIGNED_LT:
510 one_state = filter_range(orig, whole_range.min, fixed - 1);
511 two_state = filter_range(orig, fixed, whole_range.max);
512 if (left)
513 set_true_false_states(my_id, name, sym, two_state, one_state);
514 else
515 set_true_false_states(my_id, name, sym, one_state, two_state);
516 return;
517 case SPECIAL_UNSIGNED_LTE:
518 case SPECIAL_LTE:
519 one_state = filter_range(orig, whole_range.min, fixed);
520 two_state = filter_range(orig, fixed + 1, whole_range.max);
521 if (left)
522 set_true_false_states(my_id, name, sym, two_state, one_state);
523 else
524 set_true_false_states(my_id, name, sym, one_state, two_state);
525 return;
526 case SPECIAL_EQUAL:
527 // todo. print a warning here for impossible conditions.
528 one_state = alloc_extra_state(fixed);
529 two_state = filter_range(orig, fixed, fixed);
530 set_true_false_states(my_id, name, sym, one_state, two_state);
531 return;
532 case SPECIAL_UNSIGNED_GTE:
533 case SPECIAL_GTE:
534 one_state = filter_range(orig, whole_range.min, fixed - 1);
535 two_state = filter_range(orig, fixed, whole_range.max);
536 if (left)
537 set_true_false_states(my_id, name, sym, one_state, two_state);
538 else
539 set_true_false_states(my_id, name, sym, two_state, one_state);
540 return;
541 case '>':
542 case SPECIAL_UNSIGNED_GT:
543 one_state = filter_range(orig, whole_range.min, fixed);
544 two_state = filter_range(orig, fixed + 1, whole_range.max);
545 if (left)
546 set_true_false_states(my_id, name, sym, one_state, two_state);
547 else
548 set_true_false_states(my_id, name, sym, two_state, one_state);
549 return;
550 case SPECIAL_NOTEQUAL:
551 one_state = alloc_extra_state(fixed);
552 two_state = filter_range(orig, fixed, fixed);
553 set_true_false_states(my_id, name, sym, two_state, one_state);
554 return;
555 default:
556 sm_msg("unhandled comparison %d\n", comparison);
557 return;
559 return;
560 free:
561 free_string(name);
564 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
565 void __extra_match_condition(struct expression *expr)
567 struct symbol *sym;
568 char *name;
569 struct smatch_state *pre_state;
570 struct smatch_state *true_state;
571 struct smatch_state *false_state;
573 expr = strip_expr(expr);
574 switch (expr->type) {
575 case EXPR_CALL:
576 function_comparison(SPECIAL_NOTEQUAL, expr, 0, 1);
577 return;
578 case EXPR_PREOP:
579 case EXPR_SYMBOL:
580 case EXPR_DEREF:
581 name = get_variable_from_expr(expr, &sym);
582 if (!name)
583 return;
584 pre_state = get_state(my_id, name, sym);
585 true_state = add_filter(pre_state, 0);
586 false_state = alloc_extra_state(0);
587 set_true_false_states(my_id, name, sym, true_state, false_state);
588 free_string(name);
589 return;
590 case EXPR_COMPARE:
591 match_comparison(expr);
592 return;
593 case EXPR_ASSIGNMENT:
594 __extra_match_condition(expr->left);
595 return;
599 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
600 int implied_not_equal(struct expression *expr, long long val)
602 char *name;
603 struct symbol *sym;
604 struct smatch_state *state;
605 int ret = 0;
607 name = get_variable_from_expr(expr, &sym);
608 if (!name || !sym)
609 goto exit;
610 state = get_state(my_id, name, sym);
611 if (!state || !state->data)
612 goto exit;
613 ret = !possibly_false(SPECIAL_NOTEQUAL, get_dinfo(state), val, 1);
614 exit:
615 free_string(name);
616 return ret;
619 int known_condition_true(struct expression *expr)
621 long long tmp;
623 if (!expr)
624 return 0;
626 if (get_value(expr, &tmp) && tmp)
627 return 1;
629 expr = strip_expr(expr);
630 switch (expr->type) {
631 case EXPR_PREOP:
632 if (expr->op == '!') {
633 if (known_condition_false(expr->unop))
634 return 1;
635 break;
637 break;
638 default:
639 break;
641 return 0;
644 int known_condition_false(struct expression *expr)
646 if (!expr)
647 return 0;
649 if (is_zero(expr))
650 return 1;
652 switch (expr->type) {
653 case EXPR_PREOP:
654 if (expr->op == '!') {
655 if (known_condition_true(expr->unop))
656 return 1;
657 break;
659 break;
660 default:
661 break;
663 return 0;
666 static int do_comparison_range(struct expression *expr)
668 struct symbol *sym;
669 char *name;
670 struct smatch_state *state;
671 long long value;
672 int left = 0;
673 int poss_true, poss_false;
675 if (!get_value(expr->left, &value)) {
676 if (!get_value(expr->right, &value))
677 return 3;
678 left = 1;
680 if (left)
681 name = get_variable_from_expr(expr->left, &sym);
682 else
683 name = get_variable_from_expr(expr->right, &sym);
684 if (!name || !sym)
685 goto free;
686 state = get_state(SMATCH_EXTRA, name, sym);
687 if (!state)
688 goto free;
689 poss_true = possibly_true(expr->op, get_dinfo(state), value, left);
690 poss_false = possibly_false(expr->op, get_dinfo(state), value, left);
691 if (!poss_true && !poss_false)
692 return 0;
693 if (poss_true && !poss_false)
694 return 1;
695 if (!poss_true && poss_false)
696 return 2;
697 if (poss_true && poss_false)
698 return 3;
699 free:
700 free_string(name);
701 return 3;
704 int implied_condition_true(struct expression *expr)
706 struct statement *stmt;
707 long long tmp;
708 long long val;
710 if (!expr)
711 return 0;
713 if (get_value(expr, &tmp) && tmp)
714 return 1;
716 expr = strip_expr(expr);
717 switch (expr->type) {
718 case EXPR_COMPARE:
719 if (do_comparison_range(expr) == 1)
720 return 1;
721 break;
722 case EXPR_PREOP:
723 if (expr->op == '!') {
724 if (implied_condition_false(expr->unop))
725 return 1;
726 break;
728 stmt = get_block_thing(expr);
729 if (last_stmt_val(stmt, &val) && val == 1)
730 return 1;
731 break;
732 default:
733 if (implied_not_equal(expr, 0) == 1)
734 return 1;
735 break;
737 return 0;
740 int implied_condition_false(struct expression *expr)
742 struct statement *stmt;
743 struct expression *tmp;
744 long long val;
746 if (!expr)
747 return 0;
749 if (is_zero(expr))
750 return 1;
752 switch (expr->type) {
753 case EXPR_COMPARE:
754 if (do_comparison_range(expr) == 2)
755 return 1;
756 case EXPR_PREOP:
757 if (expr->op == '!') {
758 if (implied_condition_true(expr->unop))
759 return 1;
760 break;
762 stmt = get_block_thing(expr);
763 if (last_stmt_val(stmt, &val) && val == 0)
764 return 1;
765 tmp = strip_expr(expr);
766 if (tmp != expr)
767 return implied_condition_false(tmp);
768 break;
769 default:
770 if (get_implied_value(expr, &val) && val == 0)
771 return 1;
772 break;
774 return 0;
777 int get_implied_range_list(struct expression *expr, struct range_list **rl)
779 long long val;
780 struct smatch_state *state;
782 expr = strip_expr(expr);
784 state = get_state_expr(my_id, expr);
785 if (state) {
786 *rl = clone_range_list(get_dinfo(state)->value_ranges);
787 return 1;
790 if (get_implied_value(expr, &val)) {
791 *rl = NULL;
792 add_range(rl, val, val);
793 return 1;
796 if (expr->type == EXPR_BINOP && expr->op == '%') {
797 if (!get_implied_value(expr->right, &val))
798 return 0;
799 *rl = NULL;
800 add_range(rl, 0, val - 1);
801 return 1;
804 return 0;
807 void register_smatch_extra(int id)
809 my_id = id;
810 add_merge_hook(my_id, &merge_func);
811 add_unmatched_state_hook(my_id, &unmatched_state);
812 add_hook(&unop_expr, OP_HOOK);
813 add_hook(&match_function_def, FUNC_DEF_HOOK);
814 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
815 add_hook(&match_assign, ASSIGNMENT_HOOK);
816 add_hook(&match_declarations, DECLARATION_HOOK);