handle select assigns: foo = a ? b : c;
[smatch.git] / smatch_extra.c
blobdf2da1cfd889e12bfaf5f4723a2d38378fa3d501
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 data_info *alloc_dinfo(void)
35 struct data_info *ret;
37 ret = __alloc_data_info(0);
38 ret->equiv = NULL;
39 ret->type = DATA_RANGE;
40 ret->value_ranges = NULL;
41 return ret;
44 static struct data_info *alloc_dinfo_range(long long min, long long max)
46 struct data_info *ret;
48 ret = alloc_dinfo();
49 add_range(&ret->value_ranges, min, max);
50 return ret;
53 static struct data_info *alloc_dinfo_range_list(struct range_list *rl)
55 struct data_info *ret;
57 ret = alloc_dinfo();
58 ret->value_ranges = rl;
59 return ret;
62 static struct data_info *clone_dinfo(struct data_info *dinfo)
64 struct data_info *ret;
66 ret = alloc_dinfo();
67 ret->equiv = clone_tracker_list(dinfo->equiv);
68 ret->value_ranges = clone_range_list(dinfo->value_ranges);
69 return ret;
72 static struct smatch_state *clone_extra_state(struct smatch_state *state)
74 struct smatch_state *ret;
76 ret = __alloc_smatch_state(0);
77 ret->name = state->name;
78 ret->data = clone_dinfo(get_dinfo(state));
79 return ret;
82 static struct smatch_state *alloc_extra_state_empty(void)
84 struct smatch_state *state;
85 struct data_info *dinfo;
87 dinfo = alloc_dinfo();
88 state = __alloc_smatch_state(0);
89 state->data = dinfo;
90 state->name = "";
91 return state;
94 static struct smatch_state *alloc_extra_state_no_name(int val)
96 struct smatch_state *state;
98 state = __alloc_smatch_state(0);
99 state->data = (void *)alloc_dinfo_range(val, val);
100 return state;
103 /* We do this because ->value_ranges is a list */
104 struct smatch_state *extra_undefined(void)
106 struct data_info *dinfo;
107 static struct smatch_state *ret;
108 static struct symbol *prev_func;
110 if (prev_func == cur_func)
111 return ret;
112 prev_func = cur_func;
114 dinfo = alloc_dinfo_range(whole_range.min, whole_range.max);
115 ret = __alloc_smatch_state(0);
116 ret->name = "unknown";
117 ret->data = dinfo;
118 return ret;
121 struct smatch_state *alloc_extra_state(long long val)
123 struct smatch_state *state;
125 state = alloc_extra_state_no_name(val);
126 state->name = show_ranges(get_dinfo(state)->value_ranges);
127 return state;
130 struct smatch_state *alloc_extra_state_range(long long min, long long max)
132 struct smatch_state *state;
134 if (min == whole_range.min && max == whole_range.max)
135 return extra_undefined();
136 state = __alloc_smatch_state(0);
137 state->data = (void *)alloc_dinfo_range(min, max);
138 state->name = show_ranges(get_dinfo(state)->value_ranges);
139 return state;
142 struct smatch_state *alloc_extra_state_range_list(struct range_list *rl)
144 struct smatch_state *state;
146 state = __alloc_smatch_state(0);
147 state->data = (void *)alloc_dinfo_range_list(rl);
148 state->name = show_ranges(get_dinfo(state)->value_ranges);
149 return state;
152 static void add_equiv(struct smatch_state *state, const char *name, struct symbol *sym)
154 struct data_info *dinfo;
156 dinfo = get_dinfo(state);
157 add_tracker(&dinfo->equiv, SMATCH_EXTRA, name, sym);
160 static void del_equiv(struct smatch_state *state, const char *name, struct symbol *sym)
162 struct data_info *dinfo;
164 dinfo = get_dinfo(state);
165 del_tracker(&dinfo->equiv, SMATCH_EXTRA, name, sym);
168 static void remove_from_equiv(const char *name, struct symbol *sym)
170 struct sm_state *orig_sm;
171 struct tracker *tracker;
172 struct smatch_state *state;
174 orig_sm = get_sm_state(SMATCH_EXTRA, name, sym);
175 if (!orig_sm || !get_dinfo(orig_sm->state)->equiv)
176 return;
178 state = clone_extra_state(orig_sm->state);
179 del_equiv(state, name, sym);
181 FOR_EACH_PTR(get_dinfo(orig_sm->state)->equiv, tracker) {
182 struct sm_state *new_sm;
184 new_sm = clone_sm(orig_sm);
185 new_sm->name = tracker->name;
186 new_sm->sym = tracker->sym;
187 new_sm->state = state;
188 __set_sm(new_sm);
189 } END_FOR_EACH_PTR(tracker);
192 static void remove_from_equiv_expr(struct expression *expr)
194 char *name;
195 struct symbol *sym;
197 name = get_variable_from_expr(expr, &sym);
198 if (!name || !sym)
199 goto free;
200 remove_from_equiv(name, sym);
201 free:
202 free_string(name);
205 struct sm_state *set_extra_mod(const char *name, struct symbol *sym, struct smatch_state *state)
207 remove_from_equiv(name, sym);
208 return set_state(SMATCH_EXTRA, name, sym, state);
211 struct sm_state *set_extra_expr_mod(struct expression *expr, struct smatch_state *state)
213 remove_from_equiv_expr(expr);
214 return set_state_expr(SMATCH_EXTRA, expr, state);
217 void set_extra_true_false(const char *name, struct symbol *sym,
218 struct smatch_state *true_state,
219 struct smatch_state *false_state)
221 struct tracker *tracker;
222 struct smatch_state *orig_state;
224 orig_state = get_state(SMATCH_EXTRA, name, sym);
226 if (!orig_state || !get_dinfo(orig_state)->equiv) {
227 set_true_false_states(SMATCH_EXTRA, name, sym, true_state, false_state);
228 return;
231 FOR_EACH_PTR(get_dinfo(orig_state)->equiv, tracker) {
232 set_true_false_states(tracker->owner, tracker->name, tracker->sym,
233 true_state, false_state);
234 if (true_state)
235 add_equiv(true_state, tracker->name, tracker->sym);
236 if (false_state)
237 add_equiv(false_state, tracker->name, tracker->sym);
238 } END_FOR_EACH_PTR(tracker);
241 struct data_info *get_dinfo(struct smatch_state *state)
243 if (!state)
244 return NULL;
245 return (struct data_info *)state->data;
249 struct smatch_state *filter_range(struct smatch_state *orig,
250 long long filter_min, long long filter_max)
252 struct smatch_state *ret;
253 struct data_info *orig_info;
254 struct data_info *ret_info;
256 if (!orig)
257 orig = extra_undefined();
258 orig_info = get_dinfo(orig);
259 ret = alloc_extra_state_empty();
260 ret_info = get_dinfo(ret);
261 ret_info->value_ranges = remove_range(orig_info->value_ranges, filter_min, filter_max);
262 ret->name = show_ranges(ret_info->value_ranges);
263 return ret;
266 struct smatch_state *add_filter(struct smatch_state *orig, long long num)
268 return filter_range(orig, num, num);
271 static struct smatch_state *merge_func(const char *name, struct symbol *sym,
272 struct smatch_state *s1,
273 struct smatch_state *s2)
275 struct data_info *info1 = get_dinfo(s1);
276 struct data_info *info2 = get_dinfo(s2);
277 struct data_info *ret_info;
278 struct smatch_state *tmp;
279 struct range_list *value_ranges;
280 struct tracker *tracker;
282 value_ranges = range_list_union(info1->value_ranges, info2->value_ranges);
283 tmp = alloc_extra_state_empty();
284 ret_info = get_dinfo(tmp);
285 ret_info->value_ranges = value_ranges;
286 tmp->name = show_ranges(ret_info->value_ranges);
287 FOR_EACH_PTR(info1->equiv, tracker) {
288 if (in_tracker_list(info2->equiv, tracker->owner, tracker->name, tracker->sym))
289 add_equiv(tmp, tracker->name, tracker->sym);
290 } END_FOR_EACH_PTR(tracker);
291 return tmp;
294 static struct sm_state *handle_canonical_while_count_down(struct statement *loop)
296 struct expression *iter_var;
297 struct expression *condition;
298 struct sm_state *sm;
299 long long start;
301 condition = strip_expr(loop->iterator_pre_condition);
302 if (!condition)
303 return NULL;
304 if (condition->type != EXPR_PREOP && condition->type != EXPR_POSTOP)
305 return NULL;
306 if (condition->op != SPECIAL_DECREMENT)
307 return NULL;
309 iter_var = condition->unop;
310 sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
311 if (!sm)
312 return NULL;
313 if (get_dinfo_min(get_dinfo(sm->state)) < 0)
314 return NULL;
315 start = get_dinfo_max(get_dinfo(sm->state));
316 if (start <= 0)
317 return NULL;
318 if (start != whole_range.max)
319 start--;
321 if (condition->type == EXPR_PREOP)
322 set_extra_expr_mod(iter_var, alloc_extra_state_range(1, start));
323 if (condition->type == EXPR_POSTOP)
324 set_extra_expr_mod(iter_var, alloc_extra_state_range(0, start));
325 return get_sm_state_expr(SMATCH_EXTRA, iter_var);
328 static struct sm_state *handle_canonical_for_loops(struct statement *loop)
330 struct expression *iter_expr;
331 struct expression *iter_var;
332 struct expression *condition;
333 struct sm_state *sm;
334 long long start;
335 long long end;
337 if (!loop->iterator_post_statement)
338 return NULL;
339 if (loop->iterator_post_statement->type != STMT_EXPRESSION)
340 return NULL;
341 iter_expr = loop->iterator_post_statement->expression;
342 if (!loop->iterator_pre_condition)
343 return NULL;
344 if (loop->iterator_pre_condition->type != EXPR_COMPARE)
345 return NULL;
346 condition = loop->iterator_pre_condition;
349 if (iter_expr->op != SPECIAL_INCREMENT)
350 return NULL;
351 iter_var = iter_expr->unop;
352 sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
353 if (!sm)
354 return NULL;
355 if (!get_single_value_from_dinfo(get_dinfo(sm->state), &start))
356 return NULL;
357 if (!get_implied_value(condition->right, &end))
358 end = whole_range.max;
359 if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
360 return NULL;
362 switch (condition->op) {
363 case SPECIAL_NOTEQUAL:
364 case '<':
365 if (end != whole_range.max)
366 end--;
367 break;
368 case SPECIAL_LTE:
369 break;
370 default:
371 return NULL;
373 if (end < start)
374 return NULL;
375 set_extra_expr_mod(iter_var, alloc_extra_state_range(start, end));
376 return get_sm_state_expr(SMATCH_EXTRA, iter_var);
379 struct sm_state *__extra_handle_canonical_loops(struct statement *loop, struct state_list **slist)
381 struct sm_state *ret;
383 __push_fake_cur_slist();;
384 if (!loop->iterator_post_statement)
385 ret = handle_canonical_while_count_down(loop);
386 else
387 ret = handle_canonical_for_loops(loop);
388 *slist = __pop_fake_cur_slist();
389 return ret;
392 int __iterator_unchanged(struct sm_state *sm)
394 if (!sm)
395 return 0;
396 if (get_sm_state(my_id, sm->name, sm->sym) == sm)
397 return 1;
398 return 0;
401 static void while_count_down_after(struct sm_state *sm, struct expression *condition)
403 long long after_value;
405 /* paranoid checking. prolly not needed */
406 condition = strip_expr(condition);
407 if (!condition)
408 return;
409 if (condition->type != EXPR_PREOP && condition->type != EXPR_POSTOP)
410 return;
411 if (condition->op != SPECIAL_DECREMENT)
412 return;
413 after_value = get_dinfo_min(get_dinfo(sm->state));
414 after_value--;
415 set_extra_mod(sm->name, sm->sym, alloc_extra_state(after_value));
418 void __extra_pre_loop_hook_after(struct sm_state *sm,
419 struct statement *iterator,
420 struct expression *condition)
422 struct expression *iter_expr;
423 char *name;
424 struct symbol *sym;
425 long long value;
426 int left = 0;
427 struct smatch_state *state;
428 struct data_info *dinfo;
429 long long min, max;
431 if (!iterator) {
432 while_count_down_after(sm, condition);
433 return;
436 iter_expr = iterator->expression;
438 if (condition->type != EXPR_COMPARE)
439 return;
440 if (!get_value(condition->left, &value)) {
441 if (!get_value(condition->right, &value))
442 return;
443 left = 1;
445 if (left)
446 name = get_variable_from_expr(condition->left, &sym);
447 else
448 name = get_variable_from_expr(condition->right, &sym);
449 if (!name || !sym)
450 goto free;
451 if (sym != sm->sym || strcmp(name, sm->name))
452 goto free;
453 state = get_state(my_id, name, sym);
454 dinfo = get_dinfo(state);
455 min = get_dinfo_min(dinfo);
456 max = get_dinfo_max(dinfo);
457 if (iter_expr->op == SPECIAL_INCREMENT && min != whole_range.min && max == whole_range.max) {
458 set_extra_mod(name, sym, alloc_extra_state(min));
459 } else if (min == whole_range.min && max != whole_range.max) {
460 set_extra_mod(name, sym, alloc_extra_state(max));
462 free:
463 free_string(name);
464 return;
467 static struct smatch_state *unmatched_state(struct sm_state *sm)
469 return extra_undefined();
472 static void match_function_call(struct expression *expr)
474 struct expression *tmp;
475 struct symbol *sym;
476 char *name;
477 int i = 0;
479 FOR_EACH_PTR(expr->args, tmp) {
480 if (tmp->type == EXPR_PREOP && tmp->op == '&') {
481 name = get_variable_from_expr(tmp->unop, &sym);
482 if (name) {
483 set_extra_mod(name, sym, extra_undefined());
485 free_string(name);
487 i++;
488 } END_FOR_EACH_PTR(tmp);
491 static void set_equiv(struct sm_state *right_sm, struct expression *left)
493 struct smatch_state *state;
494 struct data_info *dinfo;
495 struct tracker *tracker;
496 char *name;
497 struct symbol *sym;
499 name = get_variable_from_expr(left, &sym);
500 if (!name || !sym)
501 goto free;
503 state = clone_extra_state(right_sm->state);
505 dinfo = get_dinfo(state);
506 if (!dinfo->equiv)
507 add_equiv(state, right_sm->name, right_sm->sym);
508 add_equiv(state, name, sym);
510 FOR_EACH_PTR(dinfo->equiv, tracker) {
511 struct sm_state *new_sm;
513 new_sm = clone_sm(right_sm);
514 new_sm->name = tracker->name;
515 new_sm->sym = tracker->sym;
516 new_sm->state = state;
517 __set_sm(new_sm);
518 } END_FOR_EACH_PTR(tracker);
519 free:
520 free_string(name);
523 static void match_assign(struct expression *expr)
525 struct expression *left;
526 struct expression *right;
527 struct sm_state *right_sm;
528 struct symbol *sym;
529 char *name;
530 long long value;
531 int known;
532 long long min = whole_range.min;
533 long long max = whole_range.max;
534 long long tmp;
535 struct range_list *rl = NULL;
537 left = strip_expr(expr->left);
538 name = get_variable_from_expr(left, &sym);
539 if (!name)
540 return;
541 right = strip_expr(expr->right);
542 while (right->type == EXPR_ASSIGNMENT && right->op == '=')
543 right = strip_expr(right->left);
545 right_sm = get_sm_state_expr(SMATCH_EXTRA, right);
546 if (expr->op == '=' && right_sm) {
547 set_equiv(right_sm, left);
548 goto free;
551 known = get_implied_range_list(right, &rl);
552 if (expr->op == '=') {
553 if (known)
554 set_extra_mod(name, sym, alloc_extra_state_range_list(rl));
555 else
556 set_extra_mod(name, sym, extra_undefined());
557 goto free;
560 known = get_implied_value(right, &value);
561 if (expr->op == SPECIAL_ADD_ASSIGN) {
562 if (get_implied_min(left, &tmp)) {
563 if (known)
564 min = tmp + value;
565 else
566 min = tmp;
570 if (expr->op == SPECIAL_SUB_ASSIGN) {
571 if (get_implied_max(left, &tmp)) {
572 if (known)
573 max = tmp - value;
574 else
575 max = tmp;
579 set_extra_mod(name, sym, alloc_extra_state_range(min, max));
580 free:
581 free_string(name);
584 static void unop_expr(struct expression *expr)
586 struct symbol *sym;
587 char *name;
588 long long min = whole_range.min;
589 long long max = whole_range.max;
590 long long val;
592 if (expr->op == '*')
593 return;
594 if (expr->op == '(')
595 return;
596 if (expr->op == '!')
597 return;
599 name = get_variable_from_expr(expr->unop, &sym);
600 if (!name)
601 goto free;
602 if (expr->op == SPECIAL_INCREMENT) {
603 if (get_implied_min(expr->unop, &val))
604 min = val + 1;
606 if (expr->op == SPECIAL_DECREMENT) {
607 if (get_implied_max(expr->unop, &val))
608 max = val - 1;
610 set_extra_mod(name, sym, alloc_extra_state_range(min, max));
611 free:
612 free_string(name);
615 static void delete_state_tracker(struct tracker *t)
617 remove_from_equiv(t->name, t->sym);
618 delete_state(t->owner, t->name, t->sym);
621 static void scoped_state_extra(const char *name, struct symbol *sym)
623 struct tracker *t;
625 t = alloc_tracker(SMATCH_EXTRA, name, sym);
626 add_scope_hook((scope_hook *)&delete_state_tracker, t);
629 static void match_declarations(struct symbol *sym)
631 const char *name;
632 long long val;
634 if (sym->ident) {
635 name = sym->ident->name;
636 if (sym->initializer) {
637 if (get_value(sym->initializer, &val))
638 set_state(SMATCH_EXTRA, name, sym, alloc_extra_state(val));
639 else
640 set_state(SMATCH_EXTRA, name, sym, extra_undefined());
641 scoped_state_extra(name, sym);
642 } else {
643 set_state(SMATCH_EXTRA, name, sym, extra_undefined());
644 scoped_state_extra(name, sym);
649 static void match_function_def(struct symbol *sym)
651 struct symbol *arg;
653 cur_func = sym;
654 FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
655 if (!arg->ident) {
656 continue;
658 set_state(my_id, arg->ident->name, arg, extra_undefined());
659 } END_FOR_EACH_PTR(arg);
662 static int last_stmt_val(struct statement *stmt, long long *val)
664 struct expression *expr;
666 if (!stmt)
667 return 0;
669 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
670 if (stmt->type != STMT_EXPRESSION)
671 return 0;
672 expr = stmt->expression;
673 return get_value(expr, val);
676 static void match_comparison(struct expression *expr)
678 long long fixed;
679 char *name = NULL;
680 struct symbol *sym;
681 struct smatch_state *true_state;
682 struct smatch_state *false_state;
683 struct smatch_state *orig;
684 int left = 0;
685 int comparison = expr->op;
686 struct expression *varies = expr->right;
688 if (!get_value(expr->left, &fixed)) {
689 if (!get_value(expr->right, &fixed))
690 return;
691 varies = strip_expr(expr->left);
692 left = 1;
694 if (varies->op == SPECIAL_INCREMENT || varies->op == SPECIAL_DECREMENT)
695 varies = varies->unop;
696 if (varies->type == EXPR_CALL) {
697 function_comparison(comparison, varies, fixed, left);
698 return;
701 name = get_variable_from_expr(varies, &sym);
702 if (!name || !sym)
703 goto free;
705 orig = get_state(my_id, name, sym);
706 if (!orig)
707 orig = extra_undefined();
709 switch (comparison) {
710 case '<':
711 case SPECIAL_UNSIGNED_LT:
712 if (left) {
713 true_state = filter_range(orig, fixed, whole_range.max);
714 false_state = filter_range(orig, whole_range.min, fixed - 1);
715 } else {
716 true_state = filter_range(orig, whole_range.min, fixed);
717 false_state = filter_range(orig, fixed + 1, whole_range.max);
719 break;
720 case SPECIAL_UNSIGNED_LTE:
721 case SPECIAL_LTE:
722 if (left) {
723 true_state = filter_range(orig, fixed + 1, whole_range.max);
724 false_state = filter_range(orig, whole_range.min, fixed);
725 } else {
726 true_state = filter_range(orig, whole_range.min, fixed - 1);
727 false_state = filter_range(orig, fixed, whole_range.max);
729 break;
730 case SPECIAL_EQUAL:
731 if (possibly_true(SPECIAL_EQUAL, get_dinfo(orig), fixed, fixed))
732 true_state = alloc_extra_state(fixed);
733 else
734 true_state = alloc_extra_state_empty();
735 false_state = filter_range(orig, fixed, fixed);
736 break;
737 case SPECIAL_UNSIGNED_GTE:
738 case SPECIAL_GTE:
739 if (left) {
740 true_state = filter_range(orig, whole_range.min, fixed - 1);
741 false_state = filter_range(orig, fixed, whole_range.max);
742 } else {
743 true_state = filter_range(orig, fixed + 1, whole_range.max);
744 false_state = filter_range(orig, whole_range.min, fixed);
746 break;
747 case '>':
748 case SPECIAL_UNSIGNED_GT:
749 if (left) {
750 true_state = filter_range(orig, whole_range.min, fixed);
751 false_state = filter_range(orig, fixed + 1, whole_range.max);
752 } else {
753 true_state = filter_range(orig, fixed, whole_range.max);
754 false_state = filter_range(orig, whole_range.min, fixed - 1);
756 break;
757 case SPECIAL_NOTEQUAL:
758 true_state = filter_range(orig, fixed, fixed);
759 if (possibly_true(SPECIAL_EQUAL, get_dinfo(orig), fixed, fixed))
760 false_state = alloc_extra_state(fixed);
761 else
762 false_state = alloc_extra_state_empty();
763 break;
764 default:
765 sm_msg("unhandled comparison %d\n", comparison);
766 goto free;
768 set_extra_true_false(name, sym, true_state, false_state);
769 free:
770 free_string(name);
773 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
774 void __extra_match_condition(struct expression *expr)
776 struct symbol *sym;
777 char *name;
778 struct smatch_state *pre_state;
779 struct smatch_state *true_state;
780 struct smatch_state *false_state;
782 expr = strip_expr(expr);
783 switch (expr->type) {
784 case EXPR_CALL:
785 function_comparison(SPECIAL_NOTEQUAL, expr, 0, 1);
786 return;
787 case EXPR_PREOP:
788 case EXPR_SYMBOL:
789 case EXPR_DEREF:
790 name = get_variable_from_expr(expr, &sym);
791 if (!name)
792 return;
793 pre_state = get_state(my_id, name, sym);
794 true_state = add_filter(pre_state, 0);
795 if (possibly_true(SPECIAL_EQUAL, get_dinfo(pre_state), 0, 0))
796 false_state = alloc_extra_state(0);
797 else
798 false_state = alloc_extra_state_empty();
799 set_extra_true_false(name, sym, true_state, false_state);
800 free_string(name);
801 return;
802 case EXPR_COMPARE:
803 match_comparison(expr);
804 return;
805 case EXPR_ASSIGNMENT:
806 __extra_match_condition(expr->left);
807 return;
811 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
812 int implied_not_equal(struct expression *expr, long long val)
814 char *name;
815 struct symbol *sym;
816 struct smatch_state *state;
817 int ret = 0;
819 name = get_variable_from_expr(expr, &sym);
820 if (!name || !sym)
821 goto exit;
822 state = get_state(my_id, name, sym);
823 if (!state || !state->data)
824 goto exit;
825 ret = !possibly_false(SPECIAL_NOTEQUAL, get_dinfo(state), val, 1);
826 exit:
827 free_string(name);
828 return ret;
831 int known_condition_true(struct expression *expr)
833 long long tmp;
835 if (!expr)
836 return 0;
838 if (get_value(expr, &tmp) && tmp)
839 return 1;
841 expr = strip_expr(expr);
842 switch (expr->type) {
843 case EXPR_PREOP:
844 if (expr->op == '!') {
845 if (known_condition_false(expr->unop))
846 return 1;
847 break;
849 break;
850 default:
851 break;
853 return 0;
856 int known_condition_false(struct expression *expr)
858 if (!expr)
859 return 0;
861 if (is_zero(expr))
862 return 1;
864 switch (expr->type) {
865 case EXPR_PREOP:
866 if (expr->op == '!') {
867 if (known_condition_true(expr->unop))
868 return 1;
869 break;
871 break;
872 default:
873 break;
875 return 0;
878 static int do_comparison_range(struct expression *expr)
880 struct symbol *sym;
881 char *name;
882 struct smatch_state *state;
883 long long value;
884 int left = 0;
885 int poss_true, poss_false;
887 if (!get_value(expr->left, &value)) {
888 if (!get_value(expr->right, &value))
889 return 3;
890 left = 1;
892 if (left)
893 name = get_variable_from_expr(expr->left, &sym);
894 else
895 name = get_variable_from_expr(expr->right, &sym);
896 if (!name || !sym)
897 goto free;
898 state = get_state(SMATCH_EXTRA, name, sym);
899 if (!state)
900 goto free;
901 poss_true = possibly_true(expr->op, get_dinfo(state), value, left);
902 poss_false = possibly_false(expr->op, get_dinfo(state), value, left);
903 if (!poss_true && !poss_false)
904 return 0;
905 if (poss_true && !poss_false)
906 return 1;
907 if (!poss_true && poss_false)
908 return 2;
909 if (poss_true && poss_false)
910 return 3;
911 free:
912 free_string(name);
913 return 3;
916 int implied_condition_true(struct expression *expr)
918 struct statement *stmt;
919 long long tmp;
920 long long val;
922 if (!expr)
923 return 0;
925 if (get_implied_value(expr, &tmp) && tmp)
926 return 1;
928 if (expr->type == EXPR_POSTOP)
929 return implied_condition_true(expr->unop);
931 if (expr->type == EXPR_PREOP && expr->op == SPECIAL_DECREMENT)
932 return implied_not_equal(expr->unop, 1);
933 if (expr->type == EXPR_PREOP && expr->op == SPECIAL_INCREMENT)
934 return implied_not_equal(expr->unop, -1);
936 expr = strip_expr(expr);
937 switch (expr->type) {
938 case EXPR_COMPARE:
939 if (do_comparison_range(expr) == 1)
940 return 1;
941 break;
942 case EXPR_PREOP:
943 if (expr->op == '!') {
944 if (implied_condition_false(expr->unop))
945 return 1;
946 break;
948 stmt = get_block_thing(expr);
949 if (last_stmt_val(stmt, &val) && val == 1)
950 return 1;
951 break;
952 default:
953 if (implied_not_equal(expr, 0) == 1)
954 return 1;
955 break;
957 return 0;
960 int implied_condition_false(struct expression *expr)
962 struct statement *stmt;
963 struct expression *tmp;
964 long long val;
966 if (!expr)
967 return 0;
969 if (is_zero(expr))
970 return 1;
972 switch (expr->type) {
973 case EXPR_COMPARE:
974 if (do_comparison_range(expr) == 2)
975 return 1;
976 case EXPR_PREOP:
977 if (expr->op == '!') {
978 if (implied_condition_true(expr->unop))
979 return 1;
980 break;
982 stmt = get_block_thing(expr);
983 if (last_stmt_val(stmt, &val) && val == 0)
984 return 1;
985 tmp = strip_expr(expr);
986 if (tmp != expr)
987 return implied_condition_false(tmp);
988 break;
989 default:
990 if (get_implied_value(expr, &val) && val == 0)
991 return 1;
992 break;
994 return 0;
997 int get_implied_range_list(struct expression *expr, struct range_list **rl)
999 long long val;
1000 struct smatch_state *state;
1002 expr = strip_expr(expr);
1004 state = get_state_expr(my_id, expr);
1005 if (state) {
1006 *rl = clone_range_list(get_dinfo(state)->value_ranges);
1007 return 1;
1010 if (get_implied_value(expr, &val)) {
1011 *rl = NULL;
1012 add_range(rl, val, val);
1013 return 1;
1016 if (expr->type == EXPR_BINOP && expr->op == '%') {
1017 if (!get_implied_value(expr->right, &val))
1018 return 0;
1019 *rl = NULL;
1020 add_range(rl, 0, val - 1);
1021 return 1;
1024 return 0;
1027 int is_whole_range(struct smatch_state *state)
1029 struct data_info *dinfo;
1030 struct data_range *drange;
1032 if (!state)
1033 return 0;
1034 dinfo = get_dinfo(state);
1035 drange = first_ptr_list((struct ptr_list *)dinfo->value_ranges);
1036 if (drange->min == whole_range.min && drange->max == whole_range.max)
1037 return 1;
1038 return 0;
1041 void register_smatch_extra(int id)
1043 my_id = id;
1044 add_merge_hook(my_id, &merge_func);
1045 add_unmatched_state_hook(my_id, &unmatched_state);
1046 add_hook(&unop_expr, OP_HOOK);
1047 add_hook(&match_function_def, FUNC_DEF_HOOK);
1048 add_hook(&match_function_call, FUNCTION_CALL_HOOK);
1049 add_hook(&match_assign, ASSIGNMENT_HOOK);
1050 add_hook(&match_declarations, DECLARATION_HOOK);