extra: foo((void *)&x) writes to x probably
[smatch.git] / check_bool_implications.c
blob501b4810d86a6782509504fbc84cc237e88fed40
1 /*
2 * sparse/check_bool_implications.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_extra.h"
12 #include "smatch_slist.h"
14 static int my_id;
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()))
24 return 1;
25 if (possibly_true(expr, '>', value_expr(1)))
26 return 1;
27 return 0;
30 static void handle_condition_return(struct expression *expr)
32 struct state_list *slist;
33 int was_final_pass;
35 was_final_pass = final_pass;
36 final_pass = 0;
37 __push_fake_cur_slist();
38 __split_whole_condition(expr);
39 push_slist(&true_stack, clone_slist(__get_cur_slist()));
40 __push_true_states();
41 __use_false_states();
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;
46 free_slist(&slist);
49 static void match_return(struct expression *ret_value)
51 long long val;
53 if (returns_other || !ret_value)
54 return;
56 if (non_bool(ret_value)) {
57 returns_other = 1;
58 return;
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()));
64 return;
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()));
70 return;
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;
83 if (!sym->ident)
84 return;
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)
90 return;
92 if (range_lists_equiv(estate_ranges(true_state),
93 estate_ranges(false_state)))
94 return;
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);
106 returns_other = 0;
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;
115 int i;
117 if (returns_other) {
118 cleanup();
119 return;
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);
130 i = 0;
131 FOR_EACH_PTR(sym->ctype.base_type->arguments, param_sym) {
132 print_implications(param_sym, i, merged_true, merged_false);
133 i++;
134 } END_FOR_EACH_PTR(param_sym);
137 free_slist(&merged_true);
138 free_slist(&merged_false);
140 cleanup();
143 void check_bool_implications(int id)
145 if (!option_info)
146 return;
148 my_id = id;
149 add_hook(&match_return, RETURN_HOOK);
150 add_hook(&match_end_func, END_FUNC_HOOK);