2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
11 * smatch_extra.c is supposed to track the value of every variable.
21 #include "smatch_slist.h"
22 #include "smatch_extra.h"
26 static struct symbol
*cur_func
;
28 struct data_range whole_range
= {
33 static struct data_info
*alloc_dinfo_range(long long min
, long long max
)
35 struct data_info
*ret
;
37 ret
= __alloc_data_info(0);
38 ret
->type
= DATA_RANGE
;
39 ret
->value_ranges
= NULL
;
40 add_range(&ret
->value_ranges
, min
, max
);
44 static struct data_info
*alloc_dinfo_range_list(struct range_list
*rl
)
46 struct data_info
*ret
;
48 ret
= __alloc_data_info(0);
49 ret
->type
= DATA_RANGE
;
50 ret
->value_ranges
= rl
;
54 static struct smatch_state
*alloc_extra_state_empty(void)
56 struct smatch_state
*state
;
57 struct data_info
*dinfo
;
59 dinfo
= __alloc_data_info(0);
60 dinfo
->type
= DATA_RANGE
;
61 dinfo
->value_ranges
= NULL
;
62 state
= __alloc_smatch_state(0);
67 static struct smatch_state
*alloc_extra_state_no_name(int val
)
69 struct smatch_state
*state
;
71 state
= __alloc_smatch_state(0);
72 state
->data
= (void *)alloc_dinfo_range(val
, val
);
76 /* We do this because ->value_ranges is a list */
77 struct smatch_state
*extra_undefined(void)
79 struct data_info
*dinfo
;
80 static struct smatch_state
*ret
;
81 static struct symbol
*prev_func
;
83 if (prev_func
== cur_func
)
87 dinfo
= alloc_dinfo_range(whole_range
.min
, whole_range
.max
);
88 ret
= __alloc_smatch_state(0);
89 ret
->name
= "unknown";
94 struct smatch_state
*alloc_extra_state(long long val
)
96 struct smatch_state
*state
;
98 state
= alloc_extra_state_no_name(val
);
99 state
->name
= show_ranges(get_dinfo(state
)->value_ranges
);
103 struct smatch_state
*alloc_extra_state_range(long long min
, long long max
)
105 struct smatch_state
*state
;
107 if (min
== whole_range
.min
&& max
== whole_range
.max
)
108 return extra_undefined();
109 state
= __alloc_smatch_state(0);
110 state
->data
= (void *)alloc_dinfo_range(min
, max
);
111 state
->name
= show_ranges(get_dinfo(state
)->value_ranges
);
115 struct smatch_state
*alloc_extra_state_range_list(struct range_list
*rl
)
117 struct smatch_state
*state
;
119 state
= __alloc_smatch_state(0);
120 state
->data
= (void *)alloc_dinfo_range_list(rl
);
121 state
->name
= show_ranges(get_dinfo(state
)->value_ranges
);
125 struct data_info
*get_dinfo(struct smatch_state
*state
)
129 return (struct data_info
*)state
->data
;
133 struct smatch_state
*filter_range(struct smatch_state
*orig
,
134 long long filter_min
, long long filter_max
)
136 struct smatch_state
*ret
;
137 struct data_info
*orig_info
;
138 struct data_info
*ret_info
;
141 orig
= extra_undefined();
142 orig_info
= get_dinfo(orig
);
143 ret
= alloc_extra_state_empty();
144 ret_info
= get_dinfo(ret
);
145 ret_info
->value_ranges
= remove_range(orig_info
->value_ranges
, filter_min
, filter_max
);
146 ret
->name
= show_ranges(ret_info
->value_ranges
);
150 struct smatch_state
*add_filter(struct smatch_state
*orig
, long long num
)
152 return filter_range(orig
, num
, num
);
155 static struct smatch_state
*merge_func(const char *name
, struct symbol
*sym
,
156 struct smatch_state
*s1
,
157 struct smatch_state
*s2
)
159 struct data_info
*info1
= get_dinfo(s1
);
160 struct data_info
*info2
= get_dinfo(s2
);
161 struct data_info
*ret_info
;
162 struct smatch_state
*tmp
;
163 struct range_list
*value_ranges
;
165 value_ranges
= range_list_union(info1
->value_ranges
, info2
->value_ranges
);
166 tmp
= alloc_extra_state_empty();
167 ret_info
= get_dinfo(tmp
);
168 ret_info
->value_ranges
= value_ranges
;
169 tmp
->name
= show_ranges(ret_info
->value_ranges
);
173 static struct sm_state
*handle_canonical_while_count_down(struct statement
*loop
)
175 struct expression
*iter_var
;
176 struct expression
*condition
;
180 condition
= strip_expr(loop
->iterator_pre_condition
);
183 if (condition
->type
!= EXPR_PREOP
&& condition
->type
!= EXPR_POSTOP
)
185 if (condition
->op
!= SPECIAL_DECREMENT
)
188 iter_var
= condition
->unop
;
189 sm
= get_sm_state_expr(SMATCH_EXTRA
, iter_var
);
192 if (get_dinfo_min(get_dinfo(sm
->state
)) < 0)
194 start
= get_dinfo_max(get_dinfo(sm
->state
));
197 if (start
!= whole_range
.max
)
200 if (condition
->type
== EXPR_PREOP
)
201 set_state_expr(SMATCH_EXTRA
, iter_var
, alloc_extra_state_range(1, start
));
202 if (condition
->type
== EXPR_POSTOP
)
203 set_state_expr(SMATCH_EXTRA
, iter_var
, alloc_extra_state_range(0, start
));
204 return get_sm_state_expr(SMATCH_EXTRA
, iter_var
);
207 static struct sm_state
*handle_canonical_for_loops(struct statement
*loop
)
209 struct expression
*iter_expr
;
210 struct expression
*iter_var
;
211 struct expression
*condition
;
216 if (!loop
->iterator_post_statement
)
218 if (loop
->iterator_post_statement
->type
!= STMT_EXPRESSION
)
220 iter_expr
= loop
->iterator_post_statement
->expression
;
221 if (!loop
->iterator_pre_condition
)
223 if (loop
->iterator_pre_condition
->type
!= EXPR_COMPARE
)
225 condition
= loop
->iterator_pre_condition
;
228 if (iter_expr
->op
!= SPECIAL_INCREMENT
)
230 iter_var
= iter_expr
->unop
;
231 sm
= get_sm_state_expr(SMATCH_EXTRA
, iter_var
);
234 if (!get_single_value_from_dinfo(get_dinfo(sm
->state
), &start
))
236 if (!get_implied_value(condition
->right
, &end
))
237 end
= whole_range
.max
;
238 if (get_sm_state_expr(SMATCH_EXTRA
, condition
->left
) != sm
)
241 switch (condition
->op
) {
242 case SPECIAL_NOTEQUAL
:
244 if (end
!= whole_range
.max
)
254 set_state_expr(SMATCH_EXTRA
, iter_var
, alloc_extra_state_range(start
, end
));
255 return get_sm_state_expr(SMATCH_EXTRA
, iter_var
);
258 struct sm_state
*__extra_handle_canonical_loops(struct statement
*loop
, struct state_list
**slist
)
260 struct sm_state
*ret
;
263 if (!loop
->iterator_post_statement
)
264 ret
= handle_canonical_while_count_down(loop
);
266 ret
= handle_canonical_for_loops(loop
);
267 *slist
= __fake_cur_slist
;
268 __fake_cur_slist
= NULL
;
273 int __iterator_unchanged(struct sm_state
*sm
)
277 if (get_sm_state(my_id
, sm
->name
, sm
->sym
) == sm
)
282 static void while_count_down_after(struct sm_state
*sm
, struct expression
*condition
)
284 long long after_value
;
286 /* paranoid checking. prolly not needed */
287 condition
= strip_expr(condition
);
290 if (condition
->type
!= EXPR_PREOP
&& condition
->type
!= EXPR_POSTOP
)
292 if (condition
->op
!= SPECIAL_DECREMENT
)
294 after_value
= get_dinfo_min(get_dinfo(sm
->state
));
296 set_state(SMATCH_EXTRA
, sm
->name
, sm
->sym
, alloc_extra_state(after_value
));
299 void __extra_pre_loop_hook_after(struct sm_state
*sm
,
300 struct statement
*iterator
,
301 struct expression
*condition
)
303 struct expression
*iter_expr
;
308 struct smatch_state
*state
;
309 struct data_info
*dinfo
;
313 while_count_down_after(sm
, condition
);
317 iter_expr
= iterator
->expression
;
319 if (condition
->type
!= EXPR_COMPARE
)
321 if (!get_value(condition
->left
, &value
)) {
322 if (!get_value(condition
->right
, &value
))
327 name
= get_variable_from_expr(condition
->left
, &sym
);
329 name
= get_variable_from_expr(condition
->right
, &sym
);
332 if (sym
!= sm
->sym
|| strcmp(name
, sm
->name
))
334 state
= get_state(my_id
, name
, sym
);
335 dinfo
= get_dinfo(state
);
336 min
= get_dinfo_min(dinfo
);
337 max
= get_dinfo_max(dinfo
);
338 if (iter_expr
->op
== SPECIAL_INCREMENT
&& min
!= whole_range
.min
&& max
== whole_range
.max
) {
339 set_state(my_id
, name
, sym
, alloc_extra_state(min
));
340 } else if (min
== whole_range
.min
&& max
!= whole_range
.max
) {
341 set_state(my_id
, name
, sym
, alloc_extra_state(max
));
348 static struct smatch_state
*unmatched_state(struct sm_state
*sm
)
350 return extra_undefined();
353 static void match_function_call(struct expression
*expr
)
355 struct expression
*tmp
;
360 FOR_EACH_PTR(expr
->args
, tmp
) {
361 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&') {
362 name
= get_variable_from_expr(tmp
->unop
, &sym
);
364 set_state(my_id
, name
, sym
, extra_undefined());
369 } END_FOR_EACH_PTR(tmp
);
372 static void match_assign(struct expression
*expr
)
374 struct expression
*left
;
375 struct expression
*right
;
380 long long min
= whole_range
.min
;
381 long long max
= whole_range
.max
;
383 struct range_list
*rl
= NULL
;
385 left
= strip_expr(expr
->left
);
386 name
= get_variable_from_expr(left
, &sym
);
389 right
= strip_expr(expr
->right
);
390 while (right
->type
== EXPR_ASSIGNMENT
&& right
->op
== '=')
391 right
= strip_expr(right
->left
);
393 known
= get_implied_range_list(right
, &rl
);
394 if (expr
->op
== '=') {
396 set_state(my_id
, name
, sym
, alloc_extra_state_range_list(rl
));
398 set_state(my_id
, name
, sym
, extra_undefined());
402 known
= get_implied_value(right
, &value
);
403 if (expr
->op
== SPECIAL_ADD_ASSIGN
) {
404 if (get_implied_min(left
, &tmp
)) {
412 if (expr
->op
== SPECIAL_SUB_ASSIGN
) {
413 if (get_implied_max(left
, &tmp
)) {
421 set_state(my_id
, name
, sym
, alloc_extra_state_range(min
, max
));
426 static void unop_expr(struct expression
*expr
)
430 long long min
= whole_range
.min
;
431 long long max
= whole_range
.max
;
441 name
= get_variable_from_expr(expr
->unop
, &sym
);
444 if (expr
->op
== SPECIAL_INCREMENT
) {
445 if (get_implied_min(expr
->unop
, &val
))
448 if (expr
->op
== SPECIAL_DECREMENT
) {
449 if (get_implied_max(expr
->unop
, &val
))
452 set_state(my_id
, name
, sym
, alloc_extra_state_range(min
, max
));
457 static void match_declarations(struct symbol
*sym
)
463 name
= sym
->ident
->name
;
464 if (sym
->initializer
) {
465 if (get_value(sym
->initializer
, &val
))
466 set_state(my_id
, name
, sym
, alloc_extra_state(val
));
468 set_state(my_id
, name
, sym
, extra_undefined());
469 scoped_state(my_id
, name
, sym
);
471 set_state(my_id
, name
, sym
, extra_undefined());
472 scoped_state(my_id
, name
, sym
);
477 static void match_function_def(struct symbol
*sym
)
482 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, arg
) {
486 set_state(my_id
, arg
->ident
->name
, arg
, extra_undefined());
487 } END_FOR_EACH_PTR(arg
);
494 static int get_implied_value_helper(struct expression
*expr
, long long *val
, int what
)
496 struct smatch_state
*state
;
500 if (get_value(expr
, val
))
503 name
= get_variable_from_expr(expr
, &sym
);
506 state
= get_state(my_id
, name
, sym
);
508 if (!state
|| !state
->data
)
510 if (what
== VAL_SINGLE
)
511 return get_single_value_from_dinfo(get_dinfo(state
), val
);
512 if (what
== VAL_MAX
) {
513 *val
= get_dinfo_max(get_dinfo(state
));
514 if (*val
== whole_range
.max
) /* this means just guessing */
518 *val
= get_dinfo_min(get_dinfo(state
));
519 if (*val
== whole_range
.min
)
524 int get_implied_single_val(struct expression
*expr
, long long *val
)
526 return get_implied_value_helper(expr
, val
, VAL_SINGLE
);
529 int get_implied_max(struct expression
*expr
, long long *val
)
531 return get_implied_value_helper(expr
, val
, VAL_MAX
);
534 int get_implied_min(struct expression
*expr
, long long *val
)
536 return get_implied_value_helper(expr
, val
, VAL_MIN
);
539 int get_implied_single_fuzzy_max(struct expression
*expr
, long long *max
)
542 struct sm_state
*tmp
;
544 if (get_implied_max(expr
, max
))
547 sm
= get_sm_state_expr(SMATCH_EXTRA
, expr
);
551 *max
= whole_range
.min
;
552 FOR_EACH_PTR(sm
->possible
, tmp
) {
555 new_min
= get_dinfo_min(get_dinfo(tmp
->state
));
558 } END_FOR_EACH_PTR(tmp
);
560 if (*max
> whole_range
.min
)
565 int get_implied_single_fuzzy_min(struct expression
*expr
, long long *min
)
568 struct sm_state
*tmp
;
570 if (get_implied_min(expr
, min
))
573 sm
= get_sm_state_expr(SMATCH_EXTRA
, expr
);
577 *min
= whole_range
.max
;
578 FOR_EACH_PTR(sm
->possible
, tmp
) {
581 new_max
= get_dinfo_max(get_dinfo(tmp
->state
));
584 } END_FOR_EACH_PTR(tmp
);
586 if (*min
< whole_range
.max
)
591 static int last_stmt_val(struct statement
*stmt
, long long *val
)
593 struct expression
*expr
;
598 stmt
= last_ptr_list((struct ptr_list
*)stmt
->stmts
);
599 if (stmt
->type
!= STMT_EXPRESSION
)
601 expr
= stmt
->expression
;
602 return get_value(expr
, val
);
605 static void match_comparison(struct expression
*expr
)
610 struct smatch_state
*true_state
;
611 struct smatch_state
*false_state
;
612 struct smatch_state
*orig
;
614 int comparison
= expr
->op
;
615 struct expression
*varies
= expr
->right
;
617 if (!get_value(expr
->left
, &fixed
)) {
618 if (!get_value(expr
->right
, &fixed
))
620 varies
= strip_expr(expr
->left
);
623 if (varies
->op
== SPECIAL_INCREMENT
|| varies
->op
== SPECIAL_DECREMENT
)
624 varies
= varies
->unop
;
625 if (varies
->type
== EXPR_CALL
) {
626 function_comparison(comparison
, varies
, fixed
, left
);
630 name
= get_variable_from_expr(varies
, &sym
);
634 orig
= get_state(my_id
, name
, sym
);
636 orig
= extra_undefined();
638 switch (comparison
) {
640 case SPECIAL_UNSIGNED_LT
:
642 true_state
= filter_range(orig
, fixed
, whole_range
.max
);
643 false_state
= filter_range(orig
, whole_range
.min
, fixed
- 1);
645 true_state
= filter_range(orig
, whole_range
.min
, fixed
);
646 false_state
= filter_range(orig
, fixed
+ 1, whole_range
.max
);
649 case SPECIAL_UNSIGNED_LTE
:
652 true_state
= filter_range(orig
, fixed
+ 1, whole_range
.max
);
653 false_state
= filter_range(orig
, whole_range
.min
, fixed
);
655 true_state
= filter_range(orig
, whole_range
.min
, fixed
- 1);
656 false_state
= filter_range(orig
, fixed
, whole_range
.max
);
660 // todo. print a warning here for impossible conditions.
661 true_state
= alloc_extra_state(fixed
);
662 false_state
= filter_range(orig
, fixed
, fixed
);
664 case SPECIAL_UNSIGNED_GTE
:
667 true_state
= filter_range(orig
, whole_range
.min
, fixed
- 1);
668 false_state
= filter_range(orig
, fixed
, whole_range
.max
);
670 true_state
= filter_range(orig
, fixed
+ 1, whole_range
.max
);
671 false_state
= filter_range(orig
, whole_range
.min
, fixed
);
675 case SPECIAL_UNSIGNED_GT
:
677 true_state
= filter_range(orig
, whole_range
.min
, fixed
);
678 false_state
= filter_range(orig
, fixed
+ 1, whole_range
.max
);
680 true_state
= filter_range(orig
, fixed
, whole_range
.max
);
681 false_state
= filter_range(orig
, whole_range
.min
, fixed
- 1);
684 case SPECIAL_NOTEQUAL
:
685 true_state
= filter_range(orig
, fixed
, fixed
);
686 false_state
= alloc_extra_state(fixed
);
689 sm_msg("unhandled comparison %d\n", comparison
);
692 set_true_false_states(my_id
, name
, sym
, true_state
, false_state
);
697 /* this is actually hooked from smatch_implied.c... it's hacky, yes */
698 void __extra_match_condition(struct expression
*expr
)
702 struct smatch_state
*pre_state
;
703 struct smatch_state
*true_state
;
704 struct smatch_state
*false_state
;
706 expr
= strip_expr(expr
);
707 switch (expr
->type
) {
709 function_comparison(SPECIAL_NOTEQUAL
, expr
, 0, 1);
714 name
= get_variable_from_expr(expr
, &sym
);
717 pre_state
= get_state(my_id
, name
, sym
);
718 true_state
= add_filter(pre_state
, 0);
719 if (possibly_true(SPECIAL_EQUAL
, get_dinfo(pre_state
), 0, 0))
720 false_state
= alloc_extra_state(0);
723 set_true_false_states(my_id
, name
, sym
, true_state
, false_state
);
727 match_comparison(expr
);
729 case EXPR_ASSIGNMENT
:
730 __extra_match_condition(expr
->left
);
735 /* returns 1 if it is not possible for expr to be value, otherwise returns 0 */
736 int implied_not_equal(struct expression
*expr
, long long val
)
740 struct smatch_state
*state
;
743 name
= get_variable_from_expr(expr
, &sym
);
746 state
= get_state(my_id
, name
, sym
);
747 if (!state
|| !state
->data
)
749 ret
= !possibly_false(SPECIAL_NOTEQUAL
, get_dinfo(state
), val
, 1);
755 int known_condition_true(struct expression
*expr
)
762 if (get_value(expr
, &tmp
) && tmp
)
765 expr
= strip_expr(expr
);
766 switch (expr
->type
) {
768 if (expr
->op
== '!') {
769 if (known_condition_false(expr
->unop
))
780 int known_condition_false(struct expression
*expr
)
788 switch (expr
->type
) {
790 if (expr
->op
== '!') {
791 if (known_condition_true(expr
->unop
))
802 static int do_comparison_range(struct expression
*expr
)
806 struct smatch_state
*state
;
809 int poss_true
, poss_false
;
811 if (!get_value(expr
->left
, &value
)) {
812 if (!get_value(expr
->right
, &value
))
817 name
= get_variable_from_expr(expr
->left
, &sym
);
819 name
= get_variable_from_expr(expr
->right
, &sym
);
822 state
= get_state(SMATCH_EXTRA
, name
, sym
);
825 poss_true
= possibly_true(expr
->op
, get_dinfo(state
), value
, left
);
826 poss_false
= possibly_false(expr
->op
, get_dinfo(state
), value
, left
);
827 if (!poss_true
&& !poss_false
)
829 if (poss_true
&& !poss_false
)
831 if (!poss_true
&& poss_false
)
833 if (poss_true
&& poss_false
)
840 int implied_condition_true(struct expression
*expr
)
842 struct statement
*stmt
;
849 if (get_implied_value(expr
, &tmp
) && tmp
)
852 if (expr
->type
== EXPR_POSTOP
)
853 return implied_condition_true(expr
->unop
);
855 if (expr
->type
== EXPR_PREOP
&& expr
->op
== SPECIAL_DECREMENT
)
856 return implied_not_equal(expr
->unop
, 1);
857 if (expr
->type
== EXPR_PREOP
&& expr
->op
== SPECIAL_INCREMENT
)
858 return implied_not_equal(expr
->unop
, -1);
860 expr
= strip_expr(expr
);
861 switch (expr
->type
) {
863 if (do_comparison_range(expr
) == 1)
867 if (expr
->op
== '!') {
868 if (implied_condition_false(expr
->unop
))
872 stmt
= get_block_thing(expr
);
873 if (last_stmt_val(stmt
, &val
) && val
== 1)
877 if (implied_not_equal(expr
, 0) == 1)
884 int implied_condition_false(struct expression
*expr
)
886 struct statement
*stmt
;
887 struct expression
*tmp
;
896 switch (expr
->type
) {
898 if (do_comparison_range(expr
) == 2)
901 if (expr
->op
== '!') {
902 if (implied_condition_true(expr
->unop
))
906 stmt
= get_block_thing(expr
);
907 if (last_stmt_val(stmt
, &val
) && val
== 0)
909 tmp
= strip_expr(expr
);
911 return implied_condition_false(tmp
);
914 if (get_implied_value(expr
, &val
) && val
== 0)
921 int get_implied_range_list(struct expression
*expr
, struct range_list
**rl
)
924 struct smatch_state
*state
;
926 expr
= strip_expr(expr
);
928 state
= get_state_expr(my_id
, expr
);
930 *rl
= clone_range_list(get_dinfo(state
)->value_ranges
);
934 if (get_implied_value(expr
, &val
)) {
936 add_range(rl
, val
, val
);
940 if (expr
->type
== EXPR_BINOP
&& expr
->op
== '%') {
941 if (!get_implied_value(expr
->right
, &val
))
944 add_range(rl
, 0, val
- 1);
951 int is_whole_range(struct smatch_state
*state
)
953 struct data_info
*dinfo
;
954 struct data_range
*drange
;
958 dinfo
= get_dinfo(state
);
959 drange
= first_ptr_list((struct ptr_list
*)dinfo
->value_ranges
);
960 if (drange
->min
== whole_range
.min
&& drange
->max
== whole_range
.max
)
965 void register_smatch_extra(int id
)
968 add_merge_hook(my_id
, &merge_func
);
969 add_unmatched_state_hook(my_id
, &unmatched_state
);
970 add_hook(&unop_expr
, OP_HOOK
);
971 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
972 add_hook(&match_function_call
, FUNCTION_CALL_HOOK
);
973 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
974 add_hook(&match_declarations
, DECLARATION_HOOK
);