2 * sparse/check_bool_implications.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_extra.h"
12 #include "smatch_slist.h"
16 static struct state_list_stack
*true_stack
;
17 static struct state_list_stack
*false_stack
;
19 static int returns_other
;
21 static int non_bool(struct expression
*expr
)
23 if (possibly_true(expr
, '<', zero_expr()))
25 if (possibly_true(expr
, '>', value_expr(1)))
30 static void handle_condition_return(struct expression
*expr
)
32 struct state_list
*slist
;
35 was_final_pass
= final_pass
;
37 __push_fake_cur_slist();
38 __split_whole_condition(expr
);
39 push_slist(&true_stack
, clone_slist(__get_cur_slist()));
42 push_slist(&false_stack
, clone_slist(__get_cur_slist()));
43 __merge_true_states();
44 slist
= __pop_fake_cur_slist();
45 final_pass
= was_final_pass
;
49 static void match_return(struct expression
*ret_value
)
53 if (returns_other
|| !ret_value
)
56 if (non_bool(ret_value
)) {
61 if (get_implied_value(ret_value
, &val
) && val
== 1) {
62 push_slist(&true_stack
, clone_slist(__get_cur_slist()));
66 if (get_implied_value(ret_value
, &val
) && val
== 0) {
67 push_slist(&false_stack
, clone_slist(__get_cur_slist()));
71 handle_condition_return(ret_value
);
74 static void print_implications(struct symbol
*sym
, int param
,
75 struct state_list
*true_states
,
76 struct state_list
*false_states
)
78 struct smatch_state
*true_state
;
79 struct smatch_state
*false_state
;
84 true_state
= get_state_slist(true_states
, SMATCH_EXTRA
, sym
->ident
->name
, sym
);
85 false_state
= get_state_slist(false_states
, SMATCH_EXTRA
, sym
->ident
->name
, sym
);
87 if (!true_state
|| !false_state
)
90 if (range_lists_equiv(estate_ranges(true_state
),
91 estate_ranges(false_state
)))
94 sm_msg("info: bool_return_implication \"1\" %d \"%s\" %s", param
,
95 show_ranges(estate_ranges(true_state
)), global_static());
96 sm_msg("info: bool_return_implication \"0\" %d \"%s\" %s", param
,
97 show_ranges(estate_ranges(false_state
)), global_static());
100 static void cleanup(void)
102 free_stack_and_slists(&true_stack
);
103 free_stack_and_slists(&false_stack
);
107 static void match_end_func(struct symbol
*sym
)
109 struct state_list
*merged_true
= NULL
;
110 struct state_list
*merged_false
= NULL
;
111 struct state_list
*tmp
;
112 struct symbol
*param_sym
;
120 FOR_EACH_PTR(true_stack
, tmp
) {
121 merge_slist(&merged_true
, tmp
);
122 } END_FOR_EACH_PTR(tmp
);
124 FOR_EACH_PTR(false_stack
, tmp
) {
125 merge_slist(&merged_false
, tmp
);
126 } END_FOR_EACH_PTR(tmp
);
129 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, param_sym
) {
130 print_implications(param_sym
, i
, merged_true
, merged_false
);
132 } END_FOR_EACH_PTR(param_sym
);
135 free_slist(&merged_true
);
136 free_slist(&merged_false
);
141 void check_bool_implications(int id
)
147 add_hook(&match_return
, RETURN_HOOK
);
148 add_hook(&match_end_func
, END_FUNC_HOOK
);