2 * sparse/smatch_states.c
4 * Copyright (C) 2006 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
13 #include "smatch_slist.h"
15 struct smatch_state undefined
= { .name
= "undefined" };
16 struct smatch_state true_state
= { .name
= "true" };
17 struct smatch_state false_state
= { .name
= "false" };
19 struct state_list
*cur_slist
; /* current states */
21 static struct state_list_stack
*true_stack
; /* states after a t/f branch */
22 static struct state_list_stack
*false_stack
;
23 static struct state_list_stack
*pre_cond_stack
; /* states before a t/f branch */
25 static struct state_list_stack
*cond_true_stack
; /* states affected by a branch */
26 static struct state_list_stack
*cond_false_stack
;
28 static struct state_list_stack
*break_stack
;
29 static struct state_list_stack
*switch_stack
;
30 static struct state_list_stack
*default_stack
;
31 static struct state_list_stack
*continue_stack
;
32 static struct state_list_stack
*false_only_stack
;
34 struct slist_stack
*goto_stack
;
38 void __print_slist(struct state_list
*slist
)
40 struct sm_state
*state
;
42 printf("dumping slist at %d\n", get_lineno());
43 FOR_EACH_PTR(slist
, state
) {
44 printf("'%s'=%s\n", state
->name
, state
->state
->name
);
45 } END_FOR_EACH_PTR(state
);
49 void __print_cur_slist()
51 __print_slist(cur_slist
);
54 void set_state(const char *name
, int owner
, struct symbol
*sym
, struct smatch_state
*state
)
60 struct smatch_state
*s
;
62 s
= get_state(name
, owner
, sym
);
64 printf("%d new state. name='%s' owner=%d: %s\n",
65 get_lineno(), name
, owner
, state
->name
);
67 printf("%d state change name='%s' owner=%d: %s => %s\n",
68 get_lineno(), name
, owner
, s
->name
, state
->name
);
70 set_state_slist(&cur_slist
, name
, owner
, sym
, state
);
72 if (cond_true_stack
) {
73 set_state_stack(&cond_true_stack
, name
, owner
, sym
, state
);
74 set_state_stack(&cond_false_stack
, name
, owner
, sym
, state
);
78 struct smatch_state
*get_state(const char *name
, int owner
, struct symbol
*sym
)
80 return get_state_slist(cur_slist
, name
, owner
, sym
);
83 void delete_state(const char *name
, int owner
, struct symbol
*sym
)
85 delete_state_slist(&cur_slist
, name
, owner
, sym
);
88 struct state_list
*get_current_states(int owner
)
90 struct state_list
*slist
;
93 FOR_EACH_PTR(cur_slist
, tmp
) {
94 if (tmp
->owner
== owner
) {
95 add_ptr_list(&slist
, tmp
);
97 } END_FOR_EACH_PTR(tmp
);
102 void set_true_false_states(const char *name
, int owner
, struct symbol
*sym
,
103 struct smatch_state
*true_state
, struct smatch_state
*false_state
)
105 /* fixme. save history */
108 struct smatch_state
*tmp
;
110 tmp
= get_state(name
, owner
, sym
);
111 SM_DEBUG("%d set_true_false %s. Was %s. Now T:%s F:%s\n",
112 get_lineno(), name
, (tmp
?tmp
->name
:NULL
), true_state
->name
,
116 if (!cond_false_stack
|| !cond_true_stack
) {
117 printf("Error: missing true/false stacks\n");
121 set_state_slist(&cur_slist
, name
, owner
, sym
, true_state
);
122 set_state_stack(&cond_true_stack
, name
, owner
, sym
, true_state
);
123 set_state_stack(&cond_false_stack
, name
, owner
, sym
, false_state
);
129 del_slist(&cur_slist
);
133 * At the start of every function we mark the path
134 * as unnull. That there is always at least one state
135 * in the cur_slist until nullify_path is called. This
136 * is used in merge_slist() for the first null check.
139 void __unnullify_path()
141 set_state("unnull_path", 0, NULL
, &true_state
);
144 void clear_all_states()
146 struct named_slist
*named_slist
;
149 del_slist_stack(&true_stack
);
150 del_slist_stack(&false_stack
);
151 del_slist_stack(&false_only_stack
);
152 del_slist_stack(&pre_cond_stack
);
153 del_slist_stack(&cond_true_stack
);
154 del_slist_stack(&cond_false_stack
);
155 del_slist_stack(&break_stack
);
156 del_slist_stack(&switch_stack
);
157 del_slist_stack(&continue_stack
);
159 FOR_EACH_PTR(goto_stack
, named_slist
) {
160 del_slist(&named_slist
->slist
);
161 } END_FOR_EACH_PTR(named_slist
);
162 __free_ptr_list((struct ptr_list
**)&goto_stack
);
166 void __push_cond_stacks()
168 push_slist(&cond_true_stack
, NULL
);
169 push_slist(&cond_false_stack
, NULL
);
173 * This combines the pre cond states with either the true or false states.
175 * a = kmalloc() ; if (a !! foo(a)
176 * In the pre state a is possibly null. In the true state it is non null.
177 * In the false state it is null. Combine the pre and the false to get
178 * that when we call 'foo', 'a' is null.
181 static void __use_cond_stack(struct state_list_stack
**stack
)
183 struct state_list
*slist
;
185 del_slist(&cur_slist
);
187 cur_slist
= pop_slist(&pre_cond_stack
);
188 push_slist(&pre_cond_stack
, clone_slist(cur_slist
));
190 slist
= pop_slist(stack
);
191 overwrite_slist(slist
, &cur_slist
);
192 push_slist(stack
, slist
);
196 void __use_cond_true_states()
198 __use_cond_stack(&cond_true_stack
);
201 void __use_cond_false_states()
203 __use_cond_stack(&cond_false_stack
);
206 void __negate_cond_stacks()
208 struct state_list
*old_false
, *old_true
;
210 old_false
= pop_slist(&cond_false_stack
);
211 old_true
= pop_slist(&cond_true_stack
);
213 overwrite_slist(old_false
, &cur_slist
);
215 push_slist(&cond_false_stack
, old_true
);
216 push_slist(&cond_true_stack
, old_false
);
220 void __and_cond_states()
222 struct state_list
*tmp_slist
;
224 tmp_slist
= pop_slist(&cond_true_stack
);
225 and_slist_stack(&cond_true_stack
, tmp_slist
);
226 or_slist_stack(&cond_false_stack
);
229 void __or_cond_states()
231 struct state_list
*tmp_slist
;
233 or_slist_stack(&cond_true_stack
);
234 tmp_slist
= pop_slist(&cond_false_stack
);
235 and_slist_stack(&cond_false_stack
, tmp_slist
);
239 void __save_pre_cond_states()
241 push_slist(&pre_cond_stack
, clone_slist(cur_slist
));
244 void __pop_pre_cond_states()
246 struct state_list
*tmp
;
248 tmp
= pop_slist(&pre_cond_stack
);
252 void __use_false_only_stack()
254 struct state_list
*slist
;
256 slist
= pop_slist(&false_only_stack
);
257 overwrite_slist(slist
, &cur_slist
);
261 void __pop_false_only_stack()
263 struct state_list
*slist
;
265 slist
= pop_slist(&false_only_stack
);
269 void __use_cond_states()
271 struct state_list
*pre
, *pre_clone
, *true_states
, *false_states
;
273 pre
= pop_slist(&pre_cond_stack
);
274 pre_clone
= clone_slist(pre
);
276 true_states
= pop_slist(&cond_true_stack
);
277 overwrite_slist(true_states
, &pre
);
278 /* we use the true states right away */
279 del_slist(&cur_slist
);
282 false_states
= pop_slist(&cond_false_stack
);
283 push_slist(&false_only_stack
, clone_slist(false_states
));
284 overwrite_slist(false_states
, &pre_clone
);
285 push_slist(&false_stack
, pre_clone
);
288 void __push_true_states()
290 push_slist(&true_stack
, clone_slist(cur_slist
));
293 void __use_false_states()
295 del_slist(&cur_slist
);
296 cur_slist
= pop_slist(&false_stack
);
299 void __pop_false_states()
301 struct state_list
*slist
;
303 slist
= pop_slist(&false_stack
);
307 void __merge_false_states()
309 struct state_list
*slist
;
311 slist
= pop_slist(&false_stack
);
312 merge_slist(&cur_slist
, slist
);
316 void __merge_true_states()
318 struct state_list
*slist
;
320 slist
= pop_slist(&true_stack
);
321 merge_slist(&cur_slist
, slist
);
325 void __push_continues()
327 push_slist(&continue_stack
, NULL
);
330 void __pop_continues()
332 struct state_list
*slist
;
334 slist
= pop_slist(&continue_stack
);
338 void __process_continues()
340 struct sm_state
*state
;
342 FOR_EACH_PTR(cur_slist
, state
) {
343 merge_state_stack(&continue_stack
, state
->name
, state
->owner
,
344 state
->sym
, state
->state
);
345 } END_FOR_EACH_PTR(state
);
348 void __merge_continues()
350 struct state_list
*slist
;
352 slist
= pop_slist(&continue_stack
);
353 merge_slist(&cur_slist
, slist
);
359 push_slist(&break_stack
, NULL
);
362 void __process_breaks()
364 struct state_list
*slist
;
366 slist
= pop_slist(&break_stack
);
369 overwrite_slist(cur_slist
, &slist
);
371 merge_slist(&slist
, cur_slist
);
373 push_slist(&break_stack
, slist
);
376 void __merge_breaks()
378 struct state_list
*slist
;
380 slist
= pop_slist(&break_stack
);
381 merge_slist(&cur_slist
, slist
);
387 del_slist(&cur_slist
);
388 cur_slist
= pop_slist(&break_stack
);
391 void __save_switch_states()
393 push_slist(&switch_stack
, clone_slist(cur_slist
));
396 void __merge_switches()
398 struct state_list
*slist
;
400 slist
= pop_slist(&switch_stack
);
401 merge_slist(&cur_slist
, slist
);
402 push_slist(&switch_stack
, slist
);
405 void __pop_switches()
407 struct state_list
*slist
;
409 slist
= pop_slist(&switch_stack
);
413 void __push_default()
415 push_slist(&default_stack
, NULL
);
420 set_state_stack(&default_stack
, "has_default", 0, NULL
, &true_state
);
425 struct state_list
*slist
;
427 slist
= pop_slist(&default_stack
);
435 static struct named_slist
*alloc_named_slist(const char *name
,
436 struct state_list
*slist
)
438 struct named_slist
*named_slist
= __alloc_named_slist(0);
440 named_slist
->name
= (char *)name
;
441 named_slist
->slist
= slist
;
445 void __save_gotos(const char *name
)
447 struct state_list
*slist
;
449 slist
= get_slist_from_slist_stack(goto_stack
, name
);
451 struct sm_state
*state
;
453 FOR_EACH_PTR(cur_slist
, state
) {
454 merge_state_slist(&slist
, state
->name
, state
->owner
,
455 state
->sym
, state
->state
);
456 } END_FOR_EACH_PTR(state
);
459 struct state_list
*slist
;
460 struct named_slist
*named_slist
;
462 slist
= clone_slist(cur_slist
);
463 named_slist
= alloc_named_slist(name
, slist
);
464 add_ptr_list(&goto_stack
, named_slist
);
468 void __merge_gotos(const char *name
)
470 struct state_list
*slist
;
472 slist
= get_slist_from_slist_stack(goto_stack
, name
);
474 merge_slist(&cur_slist
, slist
);