2 * smatch/smatch_comparison.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 * The point here is to store the relationships between two variables.
13 * To do that we create a state with the two variables in alphabetical order:
14 * ->name = "x vs y" and the state would be "<". On the false path the state
17 * Part of the trick of it is that if x or y is modified then we need to reset
18 * the state. We need to keep a list of all the states which depend on x and
19 * all the states which depend on y. The link_id code handles this.
21 * Future work: If we know that x is greater than y and y is greater than z
22 * then we know that x is greater than z.
26 #include "smatch_extra.h"
27 #include "smatch_slist.h"
29 static int compare_id
;
39 ALLOCATOR(compare_data
, "compare data");
41 int var_sym_eq(const char *a
, struct symbol
*a_sym
, const char *b
, struct symbol
*b_sym
)
45 if (strcmp(a
, b
) == 0)
50 static struct smatch_state
*alloc_compare_state(
51 const char *var1
, struct symbol
*sym1
,
53 const char *var2
, struct symbol
*sym2
)
55 struct smatch_state
*state
;
56 struct compare_data
*data
;
58 state
= __alloc_smatch_state(0);
59 state
->name
= alloc_sname(show_special(comparison
));
60 data
= __alloc_compare_data(0);
61 data
->var1
= alloc_sname(var1
);
63 data
->comparison
= comparison
;
64 data
->var2
= alloc_sname(var2
);
70 static int state_to_comparison(struct smatch_state
*state
)
72 if (!state
|| !state
->data
)
74 return ((struct compare_data
*)state
->data
)->comparison
;
78 * flip_op() reverses the op left and right. So "x >= y" becomes "y <= x".
80 static int flip_op(int op
)
87 case SPECIAL_UNSIGNED_LT
:
88 return SPECIAL_UNSIGNED_GT
;
91 case SPECIAL_UNSIGNED_LTE
:
92 return SPECIAL_UNSIGNED_GTE
;
95 case SPECIAL_NOTEQUAL
:
96 return SPECIAL_NOTEQUAL
;
99 case SPECIAL_UNSIGNED_GTE
:
100 return SPECIAL_UNSIGNED_LTE
;
103 case SPECIAL_UNSIGNED_GT
:
104 return SPECIAL_UNSIGNED_LT
;
106 sm_msg("internal smatch bug. unhandled comparison %d", op
);
111 static int falsify_op(int op
)
118 case SPECIAL_UNSIGNED_LT
:
119 return SPECIAL_UNSIGNED_GTE
;
122 case SPECIAL_UNSIGNED_LTE
:
123 return SPECIAL_UNSIGNED_GT
;
125 return SPECIAL_NOTEQUAL
;
126 case SPECIAL_NOTEQUAL
:
127 return SPECIAL_EQUAL
;
130 case SPECIAL_UNSIGNED_GTE
:
131 return SPECIAL_UNSIGNED_LT
;
134 case SPECIAL_UNSIGNED_GT
:
135 return SPECIAL_UNSIGNED_LTE
;
137 sm_msg("internal smatch bug. unhandled comparison %d", op
);
142 static int rl_comparison(struct range_list
*left_rl
, struct range_list
*right_rl
)
144 sval_t left_min
, left_max
, right_min
, right_max
;
146 if (!left_rl
|| !right_rl
)
149 left_min
= rl_min(left_rl
);
150 left_max
= rl_max(left_rl
);
151 right_min
= rl_min(right_rl
);
152 right_max
= rl_max(right_rl
);
154 if (left_min
.value
== left_max
.value
&&
155 right_min
.value
== right_max
.value
&&
156 left_min
.value
== right_min
.value
)
157 return SPECIAL_EQUAL
;
159 if (sval_cmp(left_max
, right_min
) < 0)
161 if (sval_cmp(left_max
, right_min
) == 0)
163 if (sval_cmp(left_min
, right_max
) > 0)
165 if (sval_cmp(left_min
, right_max
) == 0)
171 static struct range_list
*get_orig_rl(struct symbol
*sym
)
173 struct smatch_state
*state
;
175 if (!sym
|| !sym
->ident
)
177 state
= get_orig_estate(sym
->ident
->name
, sym
);
178 return estate_rl(state
);
181 static struct smatch_state
*unmatched_comparison(struct sm_state
*sm
)
183 struct compare_data
*data
= sm
->state
->data
;
184 struct range_list
*left_rl
, *right_rl
;
190 if (strstr(data
->var1
, " orig"))
191 left_rl
= get_orig_rl(data
->sym1
);
192 else if (!get_implied_rl_var_sym(data
->var1
, data
->sym1
, &left_rl
))
194 if (strstr(data
->var2
, " orig"))
195 right_rl
= get_orig_rl(data
->sym2
);
196 else if (!get_implied_rl_var_sym(data
->var2
, data
->sym2
, &right_rl
))
199 op
= rl_comparison(left_rl
, right_rl
);
201 return alloc_compare_state(data
->var1
, data
->sym1
, op
, data
->var2
, data
->sym2
);
206 /* remove_unsigned_from_comparison() is obviously a hack. */
207 static int remove_unsigned_from_comparison(int op
)
210 case SPECIAL_UNSIGNED_LT
:
212 case SPECIAL_UNSIGNED_LTE
:
214 case SPECIAL_UNSIGNED_GTE
:
216 case SPECIAL_UNSIGNED_GT
:
224 * This is for when you merge states "a < b" and "a == b", the result is that
225 * we can say for sure, "a <= b" after the merge.
227 static int merge_comparisons(int one
, int two
)
231 one
= remove_unsigned_from_comparison(one
);
232 two
= remove_unsigned_from_comparison(two
);
279 return SPECIAL_NOTEQUAL
;
290 * This is for if you have "a < b" and "b <= c". Or in other words,
291 * "a < b <= c". You would call this like get_combined_comparison('<', '<=').
292 * The return comparison would be '<'.
294 * This function is different from merge_comparisons(), for example:
295 * merge_comparison('<', '==') returns '<='
296 * get_combined_comparison('<', '==') returns '<'
298 static int combine_comparisons(int left_compare
, int right_compare
)
302 left_compare
= remove_unsigned_from_comparison(left_compare
);
303 right_compare
= remove_unsigned_from_comparison(right_compare
);
307 switch (left_compare
) {
316 return right_compare
;
325 switch (right_compare
) {
357 static struct smatch_state
*merge_compare_states(struct smatch_state
*s1
, struct smatch_state
*s2
)
359 struct compare_data
*data
= s1
->data
;
362 op
= merge_comparisons(state_to_comparison(s1
), state_to_comparison(s2
));
364 return alloc_compare_state(data
->var1
, data
->sym1
, op
, data
->var2
, data
->sym2
);
368 struct smatch_state
*alloc_link_state(struct string_list
*links
)
370 struct smatch_state
*state
;
371 static char buf
[256];
375 state
= __alloc_smatch_state(0);
378 FOR_EACH_PTR(links
, tmp
) {
380 snprintf(buf
, sizeof(buf
), "%s", tmp
);
382 append(buf
, ", ", sizeof(buf
));
383 append(buf
, tmp
, sizeof(buf
));
385 } END_FOR_EACH_PTR(tmp
);
387 state
->name
= alloc_sname(buf
);
392 static void save_start_states(struct statement
*stmt
)
394 struct symbol
*param
;
396 char state_name
[128];
397 struct smatch_state
*state
;
398 struct string_list
*links
;
401 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, param
) {
404 snprintf(orig
, sizeof(orig
), "%s orig", param
->ident
->name
);
405 snprintf(state_name
, sizeof(state_name
), "%s vs %s", param
->ident
->name
, orig
);
406 state
= alloc_compare_state(param
->ident
->name
, param
, SPECIAL_EQUAL
, alloc_sname(orig
), param
);
407 set_state(compare_id
, state_name
, NULL
, state
);
409 link
= alloc_sname(state_name
);
411 insert_string(&links
, link
);
412 state
= alloc_link_state(links
);
413 set_state(link_id
, param
->ident
->name
, param
, state
);
414 } END_FOR_EACH_PTR(param
);
417 static struct smatch_state
*merge_links(struct smatch_state
*s1
, struct smatch_state
*s2
)
419 struct smatch_state
*ret
;
420 struct string_list
*links
;
422 links
= combine_string_lists(s1
->data
, s2
->data
);
423 ret
= alloc_link_state(links
);
427 static void save_link_var_sym(const char *var
, struct symbol
*sym
, const char *link
)
429 struct smatch_state
*old_state
, *new_state
;
430 struct string_list
*links
;
433 old_state
= get_state(link_id
, var
, sym
);
435 links
= clone_str_list(old_state
->data
);
439 new = alloc_sname(link
);
440 insert_string(&links
, new);
442 new_state
= alloc_link_state(links
);
443 set_state(link_id
, var
, sym
, new_state
);
446 static void match_inc(struct sm_state
*sm
)
448 struct string_list
*links
;
449 struct smatch_state
*state
;
452 links
= sm
->state
->data
;
454 FOR_EACH_PTR(links
, tmp
) {
455 state
= get_state(compare_id
, tmp
, NULL
);
457 switch (state_to_comparison(state
)) {
460 case SPECIAL_UNSIGNED_GTE
:
462 case SPECIAL_UNSIGNED_GT
: {
463 struct compare_data
*data
= state
->data
;
464 struct smatch_state
*new;
466 new = alloc_compare_state(data
->var1
, data
->sym1
, '>', data
->var2
, data
->sym2
);
467 set_state(compare_id
, tmp
, NULL
, new);
471 set_state(compare_id
, tmp
, NULL
, &undefined
);
473 } END_FOR_EACH_PTR(tmp
);
476 static void match_dec(struct sm_state
*sm
)
478 struct string_list
*links
;
479 struct smatch_state
*state
;
482 links
= sm
->state
->data
;
484 FOR_EACH_PTR(links
, tmp
) {
485 state
= get_state(compare_id
, tmp
, NULL
);
487 switch (state_to_comparison(state
)) {
490 case SPECIAL_UNSIGNED_LTE
:
492 case SPECIAL_UNSIGNED_LT
: {
493 struct compare_data
*data
= state
->data
;
494 struct smatch_state
*new;
496 new = alloc_compare_state(data
->var1
, data
->sym1
, '<', data
->var2
, data
->sym2
);
497 set_state(compare_id
, tmp
, NULL
, new);
501 set_state(compare_id
, tmp
, NULL
, &undefined
);
503 } END_FOR_EACH_PTR(tmp
);
506 static int match_inc_dec(struct sm_state
*sm
, struct expression
*mod_expr
)
510 if (mod_expr
->type
!= EXPR_PREOP
&& mod_expr
->type
!= EXPR_POSTOP
)
513 if (mod_expr
->op
== SPECIAL_INCREMENT
) {
517 if (mod_expr
->op
== SPECIAL_DECREMENT
) {
524 static void match_modify(struct sm_state
*sm
, struct expression
*mod_expr
)
526 struct string_list
*links
;
529 if (match_inc_dec(sm
, mod_expr
))
532 links
= sm
->state
->data
;
534 FOR_EACH_PTR(links
, tmp
) {
535 set_state(compare_id
, tmp
, NULL
, &undefined
);
536 } END_FOR_EACH_PTR(tmp
);
537 set_state(link_id
, sm
->name
, sm
->sym
, &undefined
);
540 static char *chunk_to_var_sym(struct expression
*expr
, struct symbol
**sym
)
542 char *name
, *left_name
, *right_name
;
546 expr
= strip_expr(expr
);
552 name
= expr_to_var_sym(expr
, &tmp
);
561 if (expr
->type
!= EXPR_BINOP
)
563 if (expr
->op
!= '-' && expr
->op
!= '+')
566 left_name
= expr_to_var(expr
->left
);
569 right_name
= expr_to_var(expr
->right
);
571 free_string(left_name
);
574 snprintf(buf
, sizeof(buf
), "%s %s %s", left_name
, show_special(expr
->op
), right_name
);
575 free_string(left_name
);
576 free_string(right_name
);
577 return alloc_string(buf
);
580 static char *chunk_to_var(struct expression
*expr
)
582 return chunk_to_var_sym(expr
, NULL
);
585 static void save_link(struct expression
*expr
, char *link
)
590 expr
= strip_expr(expr
);
591 if (expr
->type
== EXPR_BINOP
) {
592 save_link(expr
->left
, link
);
593 save_link(expr
->right
, link
);
597 var
= expr_to_var_sym(expr
, &sym
);
601 save_link_var_sym(var
, sym
, link
);
608 static void update_tf_links(struct state_list
*pre_slist
,
609 const char *left_var
, struct symbol
*left_sym
,
611 const char *mid_var
, struct symbol
*mid_sym
,
612 struct string_list
*links
)
614 struct smatch_state
*state
;
615 struct smatch_state
*true_state
, *false_state
;
616 struct compare_data
*data
;
617 const char *right_var
;
618 struct symbol
*right_sym
;
619 int right_comparison
;
621 int false_comparison
;
623 char state_name
[256];
625 FOR_EACH_PTR(links
, tmp
) {
626 state
= get_state_slist(pre_slist
, compare_id
, tmp
, NULL
);
627 if (!state
|| !state
->data
)
630 right_comparison
= data
->comparison
;
631 right_var
= data
->var2
;
632 right_sym
= data
->sym2
;
633 if (var_sym_eq(mid_var
, mid_sym
, right_var
, right_sym
)) {
634 right_var
= data
->var1
;
635 right_sym
= data
->sym1
;
636 right_comparison
= flip_op(right_comparison
);
638 true_comparison
= combine_comparisons(left_comparison
, right_comparison
);
639 false_comparison
= combine_comparisons(falsify_op(left_comparison
), right_comparison
);
641 if (strcmp(left_var
, right_var
) > 0) {
642 struct symbol
*tmp_sym
= left_sym
;
643 const char *tmp_var
= left_var
;
645 left_var
= right_var
;
646 left_sym
= right_sym
;
649 true_comparison
= flip_op(true_comparison
);
650 false_comparison
= flip_op(false_comparison
);
653 if (!true_comparison
&& !false_comparison
)
657 true_state
= alloc_compare_state(left_var
, left_sym
, true_comparison
, right_var
, right_sym
);
660 if (false_comparison
)
661 false_state
= alloc_compare_state(left_var
, left_sym
, false_comparison
, right_var
, right_sym
);
665 snprintf(state_name
, sizeof(state_name
), "%s vs %s", left_var
, right_var
);
666 set_true_false_states(compare_id
, state_name
, NULL
, true_state
, false_state
);
667 save_link_var_sym(left_var
, left_sym
, state_name
);
668 save_link_var_sym(right_var
, right_sym
, state_name
);
669 } END_FOR_EACH_PTR(tmp
);
672 static void update_tf_data(struct state_list
*pre_slist
, struct compare_data
*tdata
)
674 struct smatch_state
*state
;
676 state
= get_state_slist(pre_slist
, link_id
, tdata
->var2
, tdata
->sym2
);
678 update_tf_links(pre_slist
, tdata
->var1
, tdata
->sym1
, tdata
->comparison
, tdata
->var2
, tdata
->sym2
, state
->data
);
680 state
= get_state_slist(pre_slist
, link_id
, tdata
->var1
, tdata
->sym1
);
682 update_tf_links(pre_slist
, tdata
->var2
, tdata
->sym2
, flip_op(tdata
->comparison
), tdata
->var1
, tdata
->sym1
, state
->data
);
685 static void match_compare(struct expression
*expr
)
689 struct symbol
*left_sym
, *right_sym
;
691 struct smatch_state
*true_state
, *false_state
;
692 char state_name
[256];
693 struct state_list
*pre_slist
;
695 if (expr
->type
!= EXPR_COMPARE
)
697 left
= chunk_to_var_sym(expr
->left
, &left_sym
);
700 right
= chunk_to_var_sym(expr
->right
, &right_sym
);
704 if (strcmp(left
, right
) > 0) {
705 struct symbol
*tmp_sym
= left_sym
;
706 char *tmp_name
= left
;
709 left_sym
= right_sym
;
712 op
= flip_op(expr
->op
);
716 false_op
= falsify_op(op
);
717 snprintf(state_name
, sizeof(state_name
), "%s vs %s", left
, right
);
718 true_state
= alloc_compare_state(left
, left_sym
, op
, right
, right_sym
);
719 false_state
= alloc_compare_state(left
, left_sym
, false_op
, right
, right_sym
);
721 pre_slist
= clone_slist(__get_cur_slist());
722 update_tf_data(pre_slist
, true_state
->data
);
723 free_slist(&pre_slist
);
725 set_true_false_states(compare_id
, state_name
, NULL
, true_state
, false_state
);
726 save_link(expr
->left
, state_name
);
727 save_link(expr
->right
, state_name
);
733 static void add_comparison_var_sym(const char *left_name
, struct symbol
*left_sym
, int comparison
, const char *right_name
, struct symbol
*right_sym
)
735 struct smatch_state
*state
;
736 char state_name
[256];
738 if (strcmp(left_name
, right_name
) > 0) {
739 struct symbol
*tmp_sym
= left_sym
;
740 const char *tmp_name
= left_name
;
742 left_name
= right_name
;
743 left_sym
= right_sym
;
744 right_name
= tmp_name
;
746 comparison
= flip_op(comparison
);
748 snprintf(state_name
, sizeof(state_name
), "%s vs %s", left_name
, right_name
);
749 state
= alloc_compare_state(left_name
, left_sym
, comparison
, right_name
, right_sym
);
751 set_state(compare_id
, state_name
, NULL
, state
);
752 save_link_var_sym(left_name
, left_sym
, state_name
);
753 save_link_var_sym(right_name
, right_sym
, state_name
);
756 static void add_comparison(struct expression
*left
, int comparison
, struct expression
*right
)
758 char *left_name
= NULL
;
759 char *right_name
= NULL
;
760 struct symbol
*left_sym
, *right_sym
;
761 struct smatch_state
*state
;
762 char state_name
[256];
764 left_name
= chunk_to_var_sym(left
, &left_sym
);
767 right_name
= chunk_to_var_sym(right
, &right_sym
);
771 if (strcmp(left_name
, right_name
) > 0) {
772 struct symbol
*tmp_sym
= left_sym
;
773 char *tmp_name
= left_name
;
775 left_name
= right_name
;
776 left_sym
= right_sym
;
777 right_name
= tmp_name
;
779 comparison
= flip_op(comparison
);
781 snprintf(state_name
, sizeof(state_name
), "%s vs %s", left_name
, right_name
);
782 state
= alloc_compare_state(left_name
, left_sym
, comparison
, right_name
, right_sym
);
784 set_state(compare_id
, state_name
, NULL
, state
);
785 save_link(left
, state_name
);
786 save_link(right
, state_name
);
789 free_string(left_name
);
790 free_string(right_name
);
793 static void match_assign_add(struct expression
*expr
)
795 struct expression
*right
;
796 struct expression
*r_left
, *r_right
;
797 sval_t left_tmp
, right_tmp
;
799 right
= strip_expr(expr
->right
);
800 r_left
= strip_expr(right
->left
);
801 r_right
= strip_expr(right
->right
);
803 get_absolute_min(r_left
, &left_tmp
);
804 get_absolute_min(r_right
, &right_tmp
);
806 if (left_tmp
.value
> 0)
807 add_comparison(expr
->left
, '>', r_right
);
808 else if (left_tmp
.value
== 0)
809 add_comparison(expr
->left
, SPECIAL_GTE
, r_right
);
811 if (right_tmp
.value
> 0)
812 add_comparison(expr
->left
, '>', r_left
);
813 else if (right_tmp
.value
== 0)
814 add_comparison(expr
->left
, SPECIAL_GTE
, r_left
);
817 static void match_assign_sub(struct expression
*expr
)
819 struct expression
*right
;
820 struct expression
*r_left
, *r_right
;
824 right
= strip_expr(expr
->right
);
825 r_left
= strip_expr(right
->left
);
826 r_right
= strip_expr(right
->right
);
828 if (get_absolute_min(r_right
, &min
) && sval_is_negative(min
))
831 comparison
= get_comparison(r_left
, r_right
);
833 switch (comparison
) {
836 if (implied_not_equal(r_right
, 0))
837 add_comparison(expr
->left
, '>', r_left
);
839 add_comparison(expr
->left
, SPECIAL_GTE
, r_left
);
844 static void match_assign_divide(struct expression
*expr
)
846 struct expression
*right
;
847 struct expression
*r_left
, *r_right
;
850 right
= strip_expr(expr
->right
);
851 r_left
= strip_expr(right
->left
);
852 r_right
= strip_expr(right
->right
);
853 if (!get_implied_min(r_right
, &min
) || min
.value
<= 1)
856 add_comparison(expr
->left
, '<', r_left
);
859 static void match_binop_assign(struct expression
*expr
)
861 struct expression
*right
;
863 right
= strip_expr(expr
->right
);
864 if (right
->op
== '+')
865 match_assign_add(expr
);
866 if (right
->op
== '-')
867 match_assign_sub(expr
);
868 if (right
->op
== '/')
869 match_assign_divide(expr
);
872 static void copy_comparisons(struct expression
*left
, struct expression
*right
)
874 struct string_list
*links
;
875 struct smatch_state
*state
;
876 struct compare_data
*data
;
877 struct symbol
*left_sym
, *right_sym
;
878 char *left_var
= NULL
;
879 char *right_var
= NULL
;
885 left_var
= chunk_to_var_sym(left
, &left_sym
);
888 right_var
= chunk_to_var_sym(right
, &right_sym
);
892 state
= get_state(link_id
, right_var
, right_sym
);
897 FOR_EACH_PTR(links
, tmp
) {
898 state
= get_state(compare_id
, tmp
, NULL
);
899 if (!state
|| !state
->data
)
902 comparison
= data
->comparison
;
905 if (var_sym_eq(var
, sym
, right_var
, right_sym
)) {
908 comparison
= flip_op(comparison
);
910 add_comparison_var_sym(left_var
, left_sym
, comparison
, var
, sym
);
911 } END_FOR_EACH_PTR(tmp
);
914 free_string(right_var
);
917 static void match_assign(struct expression
*expr
)
919 struct expression
*right
;
924 copy_comparisons(expr
->left
, expr
->right
);
925 add_comparison(expr
->left
, SPECIAL_EQUAL
, expr
->right
);
927 right
= strip_expr(expr
->right
);
928 if (right
->type
== EXPR_BINOP
)
929 match_binop_assign(expr
);
932 static int get_comparison_strings(char *one
, char *two
)
935 struct smatch_state
*state
;
939 if (strcmp(one
, two
) > 0) {
947 snprintf(buf
, sizeof(buf
), "%s vs %s", one
, two
);
948 state
= get_state(compare_id
, buf
, NULL
);
950 ret
= state_to_comparison(state
);
958 int get_comparison(struct expression
*a
, struct expression
*b
)
964 one
= chunk_to_var(a
);
967 two
= chunk_to_var(b
);
971 ret
= get_comparison_strings(one
, two
);
978 static void update_links_from_call(struct expression
*left
,
980 struct expression
*right
)
982 struct string_list
*links
;
983 struct smatch_state
*state
;
984 struct compare_data
*data
;
985 struct symbol
*left_sym
, *right_sym
;
986 char *left_var
= NULL
;
987 char *right_var
= NULL
;
993 left_var
= chunk_to_var_sym(left
, &left_sym
);
996 right_var
= chunk_to_var_sym(right
, &right_sym
);
1000 state
= get_state(link_id
, right_var
, right_sym
);
1003 links
= state
->data
;
1005 FOR_EACH_PTR(links
, tmp
) {
1006 state
= get_state(compare_id
, tmp
, NULL
);
1007 if (!state
|| !state
->data
)
1010 comparison
= data
->comparison
;
1013 if (var_sym_eq(var
, sym
, right_var
, right_sym
)) {
1016 comparison
= flip_op(comparison
);
1018 comparison
= combine_comparisons(left_compare
, comparison
);
1021 add_comparison_var_sym(left_var
, left_sym
, comparison
, var
, sym
);
1022 } END_FOR_EACH_PTR(tmp
);
1025 free_string(right_var
);
1028 void __add_comparison_info(struct expression
*expr
, struct expression
*call
, const char *range
)
1030 struct expression
*arg
;
1032 const char *c
= range
;
1034 if (!str_to_comparison_arg(c
, call
, &comparison
, &arg
))
1036 update_links_from_call(expr
, comparison
, arg
);
1037 add_comparison(expr
, comparison
, arg
);
1040 static char *range_comparison_to_param_helper(struct expression
*expr
, char starts_with
)
1042 struct symbol
*param
;
1045 char *ret_str
= NULL
;
1049 var
= chunk_to_var(expr
);
1054 FOR_EACH_PTR(cur_func_sym
->ctype
.base_type
->arguments
, param
) {
1058 snprintf(buf
, sizeof(buf
), "%s orig", param
->ident
->name
);
1059 compare
= get_comparison_strings(var
, buf
);
1062 if (show_special(compare
)[0] != starts_with
)
1064 snprintf(buf
, sizeof(buf
), "[%sp%d]", show_special(compare
), i
);
1065 ret_str
= alloc_sname(buf
);
1067 } END_FOR_EACH_PTR(param
);
1074 char *expr_equal_to_param(struct expression
*expr
)
1076 return range_comparison_to_param_helper(expr
, '=');
1079 char *expr_lte_to_param(struct expression
*expr
)
1081 return range_comparison_to_param_helper(expr
, '<');
1084 static void free_data(struct symbol
*sym
)
1088 clear_compare_data_alloc();
1091 void register_comparison(int id
)
1094 add_hook(&match_compare
, CONDITION_HOOK
);
1095 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
1096 add_hook(&save_start_states
, AFTER_DEF_HOOK
);
1097 add_unmatched_state_hook(compare_id
, unmatched_comparison
);
1098 add_merge_hook(compare_id
, &merge_compare_states
);
1099 add_hook(&free_data
, AFTER_FUNC_HOOK
);
1102 void register_comparison_links(int id
)
1105 add_merge_hook(link_id
, &merge_links
);
1106 add_modification_hook(link_id
, &match_modify
);