From 12a11e53dda8ed8883dfedb2958ea9e7d02c04e9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 27 Feb 2009 19:50:22 +0300 Subject: [PATCH] Preserve the ->pools and ->possible for implied states. With this new code, we can say that it's implied that a is either state1 or state2 but only the false path it's state3. Signed-off-by: Dan Carpenter --- smatch_implied.c | 6 ++--- smatch_slist.c | 74 +++++++++++++++++++++++++++----------------------------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/smatch_implied.c b/smatch_implied.c index 43ea309d..4fd5cd01 100644 --- a/smatch_implied.c +++ b/smatch_implied.c @@ -122,8 +122,7 @@ void __implied_states_hook(struct expression *expr) /* FIXME. We lose the ->pools by doing this. */ FOR_EACH_PTR(implied_true, state) { - set_true_false_states(state->name, state->owner, state->sym, - state->state, NULL); + __set_true_false_sm(state, NULL); } END_FOR_EACH_PTR(state); if (debug_states) { @@ -132,8 +131,7 @@ void __implied_states_hook(struct expression *expr) } FOR_EACH_PTR(implied_false, state) { - set_true_false_states(state->name, state->owner, state->sym, - NULL, state->state); + __set_true_false_sm(NULL, state); } END_FOR_EACH_PTR(state); free_string(name); diff --git a/smatch_slist.c b/smatch_slist.c index 520fbed0..1501d4a7 100644 --- a/smatch_slist.c +++ b/smatch_slist.c @@ -557,39 +557,12 @@ void merge_slist(struct state_list **to, struct state_list *slist) push_slist(&implied_pools, implied_to); } -/* - * is_currently_in_pool() is used because we remove states from pools. - * When set_state() is called then we set ->pools to NULL, but on - * other paths the state is still a member of those pools. - * Confusing huh? - * if (foo) { - * bar = 1; - * a = malloc(); - * } - * if (!a) - * return; - * if (bar) - * a->b = x; - */ -static int is_currently_in_pool(struct sm_state *sm, struct state_list *pool, - struct state_list *cur_slist) +static int pool_in_pools(struct state_list_stack *pools, + struct state_list *pool) { - struct sm_state *cur_state; struct state_list *tmp; - - cur_state = get_sm_state_slist(cur_slist, sm->name, sm->owner, sm->sym); - if (!cur_state) - return 0; - - /* if it's the current state return false because then it's the state - itself, not the state in the pool. */ - /* fixme: The above confusing comment is a load of rubbish. - this doesn't belong here, it belongs somewhere else. */ - if (sm->state == cur_state->state) - return 0; - - FOR_EACH_PTR(cur_state->pools, tmp) { + FOR_EACH_PTR(pools, tmp) { if (tmp == pool) return 1; } END_FOR_EACH_PTR(tmp); @@ -600,13 +573,18 @@ struct state_list *clone_states_in_pool(struct state_list *pool, struct state_list *cur_slist) { struct sm_state *state; + struct sm_state *cur_state; struct sm_state *tmp; struct state_list *to_slist = NULL; FOR_EACH_PTR(pool, state) { - if (state->state == &merged) + cur_state = get_sm_state_slist(cur_slist, state->name, + state->owner, state->sym); + if (!cur_state) + continue; + if (is_really_same(state, cur_state)) continue; - if (is_currently_in_pool(state, pool, cur_slist)) { + if (pool_in_pools(cur_state->pools, pool)) { tmp = clone_state(state); add_ptr_list(&to_slist, tmp); } @@ -615,6 +593,27 @@ struct state_list *clone_states_in_pool(struct state_list *pool, } /* + * merge_implied() takes an implied state and another possibly implied state + * from another pool. It checks that the second pool is reachable from + * cur_slist then merges the two states and returns the result. + */ +struct sm_state *merge_implied(struct sm_state *one, struct sm_state *two, + struct state_list *pool, + struct state_list *cur_slist) +{ + struct sm_state *cur_state; + + // fixme: do we not need to check this? + cur_state = get_sm_state_slist(cur_slist, two->name, two->owner, + two->sym); + if (!cur_state) + return NULL; /* this can't actually happen */ + if (!pool_in_pools(cur_state->pools, pool)) + return NULL; + return merge_sm_states(one, two); +} + +/* * filter() is used to find what states are the same across * a series of slists. * It takes a **slist and a *filter. @@ -627,6 +626,7 @@ void filter(struct state_list **slist, struct state_list *filter, { struct sm_state *s_one, *s_two; struct state_list *results = NULL; + struct sm_state *tmp; #ifdef CHECKORDER check_order(*slist); @@ -641,13 +641,9 @@ void filter(struct state_list **slist, struct state_list *filter, if (cmp_tracker(s_one, s_two) < 0) { NEXT_PTR_LIST(s_one); } else if (cmp_tracker(s_one, s_two) == 0) { - /* todo. pointer comparison works fine for most things - except smatch_extra. we may need a hook here. */ - if (s_one->state == s_two->state && - is_currently_in_pool(s_two, filter, cur_slist) - && s_one->state != &merged) { - add_ptr_list(&results, s_one); - } + tmp = merge_implied(s_one, s_two, filter, cur_slist); + if (tmp) + add_ptr_list(&results, tmp); NEXT_PTR_LIST(s_one); NEXT_PTR_LIST(s_two); } else { -- 2.11.4.GIT