From bc80c86e05bba07482b62933a73e44292de0a560 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Jun 2013 12:38:06 +0300 Subject: [PATCH] comparison: fix bug handling min_t() The problem is that when we parsed a condition we were using the states we had just written to determine the other states. We have to save the states first and use the original states. Signed-off-by: Dan Carpenter --- smatch_comparison.c | 20 ++++++++++++-------- validation/sm_compare12.c | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 validation/sm_compare12.c diff --git a/smatch_comparison.c b/smatch_comparison.c index 0aa17062..09e9260e 100644 --- a/smatch_comparison.c +++ b/smatch_comparison.c @@ -608,7 +608,8 @@ done: -static void update_tf_links(const char *left_var, struct symbol *left_sym, +static void update_tf_links(struct state_list *pre_slist, + const char *left_var, struct symbol *left_sym, int left_comparison, const char *mid_var, struct symbol *mid_sym, struct string_list *links) @@ -625,7 +626,7 @@ static void update_tf_links(const char *left_var, struct symbol *left_sym, char state_name[256]; FOR_EACH_PTR(links, tmp) { - state = get_state(compare_id, tmp, NULL); + state = get_state_slist(pre_slist, compare_id, tmp, NULL); if (!state || !state->data) continue; data = state->data; @@ -671,17 +672,17 @@ static void update_tf_links(const char *left_var, struct symbol *left_sym, } END_FOR_EACH_PTR(tmp); } -static void update_tf_data(struct compare_data *tdata) +static void update_tf_data(struct state_list *pre_slist, struct compare_data *tdata) { struct smatch_state *state; - state = get_state(link_id, tdata->var2, tdata->sym2); + state = get_state_slist(pre_slist, link_id, tdata->var2, tdata->sym2); if (state) - update_tf_links(tdata->var1, tdata->sym1, tdata->comparison, tdata->var2, tdata->sym2, state->data); + update_tf_links(pre_slist, tdata->var1, tdata->sym1, tdata->comparison, tdata->var2, tdata->sym2, state->data); - state = get_state(link_id, tdata->var1, tdata->sym1); + state = get_state_slist(pre_slist, link_id, tdata->var1, tdata->sym1); if (state) - update_tf_links(tdata->var2, tdata->sym2, flip_op(tdata->comparison), tdata->var1, tdata->sym1, state->data); + update_tf_links(pre_slist, tdata->var2, tdata->sym2, flip_op(tdata->comparison), tdata->var1, tdata->sym1, state->data); } static void match_compare(struct expression *expr) @@ -692,6 +693,7 @@ static void match_compare(struct expression *expr) int op, false_op; struct smatch_state *true_state, *false_state; char state_name[256]; + struct state_list *pre_slist; if (expr->type != EXPR_COMPARE) return; @@ -719,7 +721,9 @@ static void match_compare(struct expression *expr) true_state = alloc_compare_state(left, left_sym, op, right, right_sym); false_state = alloc_compare_state(left, left_sym, false_op, right, right_sym); - update_tf_data(true_state->data); + pre_slist = clone_slist(__get_cur_slist()); + update_tf_data(pre_slist, true_state->data); + free_slist(&pre_slist); set_true_false_states(compare_id, state_name, NULL, true_state, false_state); save_link(expr->left, state_name); diff --git a/validation/sm_compare12.c b/validation/sm_compare12.c new file mode 100644 index 00000000..2f520731 --- /dev/null +++ b/validation/sm_compare12.c @@ -0,0 +1,24 @@ +#include "check_debug.h" + +#define min_t(type, x, y) ({ \ + type __min1 = (x); \ + type __min2 = (y); \ + __min1 < __min2 ? __min1: __min2; }) + +int a, b, c, d; +static int options_write(void) +{ + a = min_t(int, b + c, d); + __smatch_compare(a, d); + __smatch_compare(a, b + c); +} + +/* + * check-name: smatch compare #12 + * check-command: smatch -I.. sm_compare12.c + * + * check-output-start +sm_compare12.c:12 options_write() a <= d +sm_compare12.c:13 options_write() a <= b + c + * check-output-end + */ -- 2.11.4.GIT