From 0c0395ef24091518c34fc04738cedae647e0aaa9 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 11 Feb 2009 15:55:51 +0300 Subject: [PATCH] Remove a state from it's ->pools when set_state() is called. There are old implied pools out there. When we set the state all the things that were implied previously are not implied now. if (foo) { bar = 1; } bar = 0; non null foo doesn't implied bar == 1 anymore. Signed-off-by: Dan Carpenter --- smatch_slist.c | 18 ++++++++++++++++++ smatch_slist.h | 1 + smatch_states.c | 26 +++++++++++++++----------- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/smatch_slist.c b/smatch_slist.c index 36cc13c8..2ef6c3a1 100644 --- a/smatch_slist.c +++ b/smatch_slist.c @@ -478,6 +478,24 @@ void merge_slist(struct state_list **to, struct state_list *slist) } /* + * If you call set_state() then you need to remove + * the state from any pools it's in. Just setting ->pools + * to NULL isn't enough. + */ +void remove_from_pools(struct sm_state *old) +{ + struct state_list *slist; + + if (!old) + return; + + FOR_EACH_PTR(old->pools, slist) { + delete_state_slist(&slist, old->name, old->owner, old->sym); + } END_FOR_EACH_PTR(slist); +} + + +/* * filter() is used to find what states are the same across * a series of slists. * It takes a **slist and a *filter. diff --git a/smatch_slist.h b/smatch_slist.h index d192dc13..09533261 100644 --- a/smatch_slist.h +++ b/smatch_slist.h @@ -74,6 +74,7 @@ struct smatch_state *get_state_stack(struct state_list_stack *stack, const char int owner, struct symbol *sym); void merge_slist(struct state_list **to, struct state_list *slist); +void remove_from_pools(struct sm_state *old); void filter(struct state_list **slist, struct state_list *filter); void and_slist_stack(struct state_list_stack **slist_stack); diff --git a/smatch_states.c b/smatch_states.c index 0784aba4..15eb3d58 100644 --- a/smatch_states.c +++ b/smatch_states.c @@ -63,21 +63,24 @@ void __print_cur_slist() void set_state(const char *name, int owner, struct symbol *sym, struct smatch_state *state) { + struct sm_state *old; + if (!name) return; + old = __get_sm_state(name, owner, sym); + if (debug_states) { - struct smatch_state *s; - - s = get_state(name, owner, sym); - if (!s) + if (!old) printf("%d new state. name='%s' owner=%d: %s\n", get_lineno(), name, owner, show_state(state)); else printf("%d state change name='%s' owner=%d: %s => %s\n", - get_lineno(), name, owner, show_state(s), - show_state(state)); + get_lineno(), name, owner, + show_state(old->state), show_state(state)); } + + remove_from_pools(old); set_state_slist(&cur_slist, name, owner, sym, state); if (cond_true_stack) { @@ -135,15 +138,14 @@ void set_true_false_states(const char *name, int owner, struct symbol *sym, struct smatch_state *true_state, struct smatch_state *false_state) { + struct sm_state *old; /* fixme. save history */ + old = __get_sm_state(name, owner, sym); if (debug_states) { - struct smatch_state *tmp; - - tmp = get_state(name, owner, sym); SM_DEBUG("%d set_true_false '%s'. Was %s. Now T:%s F:%s\n", - get_lineno(), name, show_state(tmp), - show_state(true_state), show_state(false_state)); + get_lineno(), name, (old?show_state(old->state):NULL), + show_state(true_state), show_state(false_state)); } if (!cond_false_stack || !cond_true_stack) { @@ -151,6 +153,8 @@ void set_true_false_states(const char *name, int owner, struct symbol *sym, return; } + remove_from_pools(old); + if (true_state) { set_state_slist(&cur_slist, name, owner, sym, true_state); set_state_stack(&cond_true_stack, name, owner, sym, true_state); -- 2.11.4.GIT