From f02c544c51a4b679dd8092528e8fb88c30716966 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 13 May 2010 14:50:43 +0200 Subject: [PATCH] implied: allow the known part to be a range list So implications basically works like this: if (x == 42) { ... If x is a merged state then it potentially has implications. So we take the 42 and the pools from x and figure out where the condition is true. But what about if, instead of 42 we have y? In the current code if y is a single value like this: y = 42; if (x == 42) { ... The current code can handle that. The thing it can't handle is if y is a range like 4-10. This patch tries to address that. Signed-off-by: Dan Carpenter --- smatch_extra.c | 2 +- smatch_extra.h | 1 + smatch_implied.c | 57 +++++++++++++++++++++++++------------------------------- 3 files changed, 27 insertions(+), 33 deletions(-) diff --git a/smatch_extra.c b/smatch_extra.c index a332ac89..8714bcc8 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -910,7 +910,7 @@ int known_condition_false(struct expression *expr) return 0; } -static struct range_list *get_range_list(struct expression *expr) +struct range_list *get_range_list(struct expression *expr) { long long min; long long max; diff --git a/smatch_extra.h b/smatch_extra.h index 97790ea4..a67a4a17 100644 --- a/smatch_extra.h +++ b/smatch_extra.h @@ -51,6 +51,7 @@ struct sm_state *set_extra_expr_mod(struct expression *expr, struct smatch_state void set_extra_expr_nomod(struct expression *expr, struct smatch_state *state); struct smatch_state *alloc_extra_state(long long val); struct smatch_state *alloc_extra_state_range_list(struct range_list *rl); +struct range_list *get_range_list(struct expression *expr); struct data_info *get_dinfo(struct smatch_state *state); struct smatch_state *add_filter(struct smatch_state *orig, long long filter); struct smatch_state *extra_undefined(void); diff --git a/smatch_implied.c b/smatch_implied.c index 4a565a13..d2e7c682 100644 --- a/smatch_implied.c +++ b/smatch_implied.c @@ -348,26 +348,25 @@ static void separate_and_filter(struct sm_state *sm_state, int comparison, struc __bail_on_rest_of_function = 1; } -static char *get_implication_variable(struct expression *expr, struct symbol **symp) +static struct sm_state *get_left_most_sm(struct expression *expr) { expr = strip_expr(expr); if (expr->type == EXPR_ASSIGNMENT) - return get_implication_variable(expr->left, symp); - return get_variable_from_expr(expr, symp); + return get_left_most_sm(expr->left); + return get_sm_state_expr(SMATCH_EXTRA, expr); } -static int get_known_value(struct expression *expr, long long *val) +static int is_merged_expr(struct expression *expr) { struct sm_state *sm; + long long dummy; - if (get_value(expr, val)) - return 1; + if (get_value(expr, &dummy)) + return 0; sm = get_sm_state_expr(SMATCH_EXTRA, expr); if (!sm) return 0; - if (!get_single_value_from_dinfo(get_dinfo(sm->state), val)) - return 0; - if (!is_implied(sm)) + if (is_merged(sm)) return 1; return 0; } @@ -394,35 +393,29 @@ static void handle_comparison(struct expression *expr, struct state_list **implied_true, struct state_list **implied_false) { - struct symbol *sym; - char *name; - struct sm_state *sm; - long long value; + struct sm_state *sm = NULL; + struct range_list *ranges = NULL; int lr; - if (get_known_value(expr->right, &value)) + if (is_merged_expr(expr->left)) { lr = LEFT; - else if (get_known_value(expr->left, &value)) + sm = get_left_most_sm(expr->left); + ranges = get_range_list(expr->right); + } else if (is_merged_expr(expr->right)) { lr = RIGHT; - else - return; - - if (lr == LEFT) - name = get_implication_variable(expr->left, &sym); - else - name = get_implication_variable(expr->right, &sym); - if (!name || !sym) - goto free; + sm = get_left_most_sm(expr->right); + ranges = get_range_list(expr->left); + } - sm = get_sm_state(SMATCH_EXTRA, name, sym); - if (!sm) - goto free; + if (!ranges || !sm) { + free_range_list(&ranges); + return; + } - separate_and_filter(sm, expr->op, tmp_range_list(value), lr, __get_cur_slist(), implied_true, implied_false); - delete_equiv_slist(implied_true, name, sym); - delete_equiv_slist(implied_false, name, sym); -free: - free_string(name); + separate_and_filter(sm, expr->op, ranges, lr, __get_cur_slist(), implied_true, implied_false); + free_range_list(&ranges); + delete_equiv_slist(implied_true, sm->name, sm->sym); + delete_equiv_slist(implied_false, sm->name, sm->sym); } static void handle_zero_comparison(struct expression *expr, -- 2.11.4.GIT