whitespace: add a newline
[smatch.git] / check_bool_implications.c
blob5ff6a7ebb5bbbd3bccad9a4dc4773c2a4f07f1a6
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 push_slist(&true_stack, clone_slist(__get_cur_slist()));
63 return;
66 if (get_implied_value(ret_value, &val) && val == 0) {
67 push_slist(&false_stack, clone_slist(__get_cur_slist()));
68 return;
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;
81 if (!sym->ident)
82 return;
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)
88 return;
90 if (range_lists_equiv(estate_ranges(true_state),
91 estate_ranges(false_state)))
92 return;
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);
104 returns_other = 0;
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;
113 int i;
115 if (returns_other) {
116 cleanup();
117 return;
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);
128 i = 0;
129 FOR_EACH_PTR(sym->ctype.base_type->arguments, param_sym) {
130 print_implications(param_sym, i, merged_true, merged_false);
131 i++;
132 } END_FOR_EACH_PTR(param_sym);
135 free_slist(&merged_true);
136 free_slist(&merged_false);
138 cleanup();
141 void check_bool_implications(int id)
143 if (!option_info)
144 return;
146 my_id = id;
147 add_hook(&match_return, RETURN_HOOK);
148 add_hook(&match_end_func, END_FUNC_HOOK);