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 sm_msg("added to true_stack");
63 push_slist(&true_stack
, clone_slist(__get_cur_slist()));
67 if (get_implied_value(ret_value
, &val
) && val
== 0) {
68 sm_msg("added to false_stack");
69 push_slist(&false_stack
, clone_slist(__get_cur_slist()));
73 handle_condition_return(ret_value
);
76 static void print_implications(struct symbol
*sym
, int param
,
77 struct state_list
*true_states
,
78 struct state_list
*false_states
)
80 struct smatch_state
*true_state
;
81 struct smatch_state
*false_state
;
86 true_state
= get_state_slist(true_states
, SMATCH_EXTRA
, sym
->ident
->name
, sym
);
87 false_state
= get_state_slist(false_states
, SMATCH_EXTRA
, sym
->ident
->name
, sym
);
89 if (!true_state
|| !false_state
)
92 if (range_lists_equiv(estate_ranges(true_state
),
93 estate_ranges(false_state
)))
96 sm_msg("info: bool_return_implication \"1\" %d \"%s\"", param
,
97 show_ranges(estate_ranges(true_state
)));
98 sm_msg("info: bool_return_implication \"0\" %d \"%s\"", param
,
99 show_ranges(estate_ranges(false_state
)));
102 static void cleanup(void)
104 free_stack_and_slists(&true_stack
);
105 free_stack_and_slists(&false_stack
);
109 static void match_end_func(struct symbol
*sym
)
111 struct state_list
*merged_true
= NULL
;
112 struct state_list
*merged_false
= NULL
;
113 struct state_list
*tmp
;
114 struct symbol
*param_sym
;
122 FOR_EACH_PTR(true_stack
, tmp
) {
123 merge_slist(&merged_true
, tmp
);
124 } END_FOR_EACH_PTR(tmp
);
126 FOR_EACH_PTR(false_stack
, tmp
) {
127 merge_slist(&merged_false
, tmp
);
128 } END_FOR_EACH_PTR(tmp
);
131 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, param_sym
) {
132 print_implications(param_sym
, i
, merged_true
, merged_false
);
134 } END_FOR_EACH_PTR(param_sym
);
137 free_slist(&merged_true
);
138 free_slist(&merged_false
);
143 void check_bool_implications(int id
)
149 add_hook(&match_return
, RETURN_HOOK
);
150 add_hook(&match_end_func
, END_FUNC_HOOK
);