2 * sparse/smatch_stored_conditions.c
4 * Copyright (C) 2014 Oracle.
6 * Licensed under the Open Software License version 1.1
11 * Keep a record of all the things we have tested for so that we know when we
12 * test for it again. For example, if we have code like this:
22 * That's the end goal at least. But actually implementing the flow of that
23 * requires quite a bit of work because if "foo" changes the condition needs to
24 * be retested and smatch_implications.c needs to be updated.
26 * For now, I just record the conditions and use it to see if we test for NULL
32 #include "smatch_slist.h"
37 static struct smatch_state
*alloc_link_state(struct string_list
*links
)
39 struct smatch_state
*state
;
44 state
= __alloc_smatch_state(0);
47 FOR_EACH_PTR(links
, tmp
) {
49 snprintf(buf
, sizeof(buf
), "%s", tmp
);
51 append(buf
, ", ", sizeof(buf
));
52 append(buf
, tmp
, sizeof(buf
));
54 } END_FOR_EACH_PTR(tmp
);
56 state
->name
= alloc_sname(buf
);
61 static struct smatch_state
*merge_links(struct smatch_state
*s1
, struct smatch_state
*s2
)
63 struct smatch_state
*ret
;
64 struct string_list
*links
;
66 links
= combine_string_lists(s1
->data
, s2
->data
);
67 ret
= alloc_link_state(links
);
71 static void save_link_var_sym(const char *var
, struct symbol
*sym
, const char *link
)
73 struct smatch_state
*old_state
, *new_state
;
74 struct string_list
*links
;
77 old_state
= get_state(link_id
, var
, sym
);
79 links
= clone_str_list(old_state
->data
);
83 new = alloc_sname(link
);
84 insert_string(&links
, new);
86 new_state
= alloc_link_state(links
);
87 set_state(link_id
, var
, sym
, new_state
);
90 static void match_modify(struct sm_state
*sm
, struct expression
*mod_expr
)
92 struct string_list
*links
;
95 links
= sm
->state
->data
;
97 FOR_EACH_PTR(links
, tmp
) {
98 set_state(my_id
, tmp
, NULL
, &undefined
);
99 } END_FOR_EACH_PTR(tmp
);
100 set_state(link_id
, sm
->name
, sm
->sym
, &undefined
);
103 static struct smatch_state
*alloc_state(struct expression
*expr
, int is_true
)
105 struct smatch_state
*state
;
107 state
= __alloc_smatch_state(0);
109 state
->name
= alloc_sname("true");
111 state
->name
= alloc_sname("false");
116 static int is_local_variable(struct expression
*expr
)
121 name
= expr_to_var_sym(expr
, &sym
);
123 if (!sym
|| !sym
->scope
|| !sym
->scope
->token
)
125 if (cmp_pos(sym
->scope
->token
->pos
, cur_func_sym
->pos
) < 0)
132 static int get_complication_score(struct expression
*expr
)
136 expr
= strip_expr(expr
);
138 switch (expr
->type
) {
143 score
+= get_complication_score(expr
->left
);
144 score
+= get_complication_score(expr
->right
);
147 if (is_local_variable(expr
))
154 if (expr
->op
== SPECIAL_INCREMENT
||
155 expr
->op
== SPECIAL_DECREMENT
)
157 return get_complication_score(expr
->unop
);
164 static int condition_too_complicated(struct expression
*expr
)
166 if (get_complication_score(expr
) > 2)
172 static void store_all_links(struct expression
*expr
, const char *condition
)
177 expr
= strip_expr(expr
);
179 switch (expr
->type
) {
181 store_all_links(expr
->left
, condition
);
182 store_all_links(expr
->right
, condition
);
188 var
= expr_to_var_sym(expr
, &sym
);
191 save_link_var_sym(var
, sym
, condition
);
196 static void match_condition(struct expression
*expr
)
198 struct smatch_state
*true_state
, *false_state
;
201 if (condition_too_complicated(expr
))
204 name
= expr_to_str(expr
);
207 true_state
= alloc_state(expr
, TRUE
);
208 false_state
= alloc_state(expr
, FALSE
);
209 set_true_false_states(my_id
, name
, NULL
, true_state
, false_state
);
210 store_all_links(expr
, alloc_sname(name
));
214 struct smatch_state
*get_stored_condition(struct expression
*expr
)
216 struct smatch_state
*state
;
219 name
= expr_to_str(expr
);
223 state
= get_state(my_id
, name
, NULL
);
228 void register_stored_conditions(int id
)
232 add_hook(&match_condition
, CONDITION_HOOK
);
235 void register_stored_conditions_links(int id
)
238 add_merge_hook(link_id
, &merge_links
);
239 add_modification_hook(link_id
, &match_modify
);