From 150eee63739c6c1b9e980fef5c19fa870a5eab91 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 12 Apr 2016 13:47:22 +0300 Subject: [PATCH] flow: shuffle case statement handling around Give a range list to smatch_implied instead of a case_expression and a case_to expression. Signed-off-by: Dan Carpenter --- smatch.h | 9 ++++----- smatch_flow.c | 24 ++++++++++++++++++------ smatch_implied.c | 38 +++++++++++--------------------------- smatch_states.c | 4 ++-- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/smatch.h b/smatch.h index fd7b2cc3..ba0060aa 100644 --- a/smatch.h +++ b/smatch.h @@ -455,10 +455,9 @@ extern int option_debug_related; struct range_list_stack; void param_limit_implications(struct expression *expr, int param, char *key, char *value); struct stree *__implied_case_stree(struct expression *switch_expr, - struct expression *case_expr, - struct expression *case_to, - struct range_list_stack **remaining_cases, - struct stree **raw_stree); + struct range_list *case_rl, + struct range_list_stack **remaining_cases, + struct stree **raw_stree); struct range_list *__get_implied_values(struct expression *switch_expr); void overwrite_states_using_pool(struct sm_state *sm); void add_pool(struct stree_stack **pools, struct stree *new); @@ -614,7 +613,7 @@ void __use_breaks(void); void __save_switch_states(struct expression *switch_expr); void __discard_switches(void); -void __merge_switches(struct expression *switch_expr, struct expression *case_expr, struct expression *case_to); +void __merge_switches(struct expression *switch_expr, struct range_list *case_rl); void __push_default(void); void __set_default(void); int __pop_default(void); diff --git a/smatch_flow.c b/smatch_flow.c index ba1b57df..23bdf8d0 100644 --- a/smatch_flow.c +++ b/smatch_flow.c @@ -693,6 +693,20 @@ static int is_case_val(struct statement *stmt, sval_t sval) return 0; } +static struct range_list *get_case_rl(struct expression *case_expr, + struct expression *case_to) +{ + sval_t start, end; + struct range_list *rl = NULL; + + if (get_value(case_to, &end) && get_value(case_expr, &start)) { + add_range(&rl, start, end); + } else if (get_value(case_expr, &start)) { + add_range(&rl, start, start); + } + + return rl; +} static void split_known_switch(struct statement *stmt, sval_t sval) { struct statement *tmp; @@ -712,7 +726,7 @@ static void split_known_switch(struct statement *stmt, sval_t sval) __smatch_lineno = tmp->pos.line; if (is_case_val(tmp, sval)) { __merge_switches(top_expression(switch_expr_stack), - stmt->case_expression, stmt->case_to); + get_case_rl(stmt->case_expression, stmt->case_to)); __pass_case_to_client(top_expression(switch_expr_stack), stmt->case_expression); } @@ -727,8 +741,7 @@ static void split_known_switch(struct statement *stmt, sval_t sval) out: __call_scope_hooks(); if (!__pop_default()) - __merge_switches(top_expression(switch_expr_stack), - NULL, NULL); + __merge_switches(top_expression(switch_expr_stack), NULL); __discard_switches(); __merge_breaks(); pop_expression(&switch_expr_stack); @@ -957,15 +970,14 @@ void __split_stmt(struct statement *stmt) __push_breaks(); __split_stmt(stmt->switch_statement); if (!__pop_default()) - __merge_switches(top_expression(switch_expr_stack), - NULL, NULL); + __merge_switches(top_expression(switch_expr_stack), NULL); __discard_switches(); __merge_breaks(); pop_expression(&switch_expr_stack); break; case STMT_CASE: __merge_switches(top_expression(switch_expr_stack), - stmt->case_expression, stmt->case_to); + get_case_rl(stmt->case_expression, stmt->case_to)); __pass_case_to_client(top_expression(switch_expr_stack), stmt->case_expression); if (!stmt->case_expression) diff --git a/smatch_implied.c b/smatch_implied.c index e6390580..98dce0a1 100644 --- a/smatch_implied.c +++ b/smatch_implied.c @@ -712,12 +712,12 @@ free: return ret; } -struct stree *__implied_case_stree_rl(struct expression *switch_expr, - struct range_list *rl, - struct range_list_stack **remaining_cases, - struct stree **raw_stree) +struct stree *__implied_case_stree(struct expression *switch_expr, + struct range_list *rl, + struct range_list_stack **remaining_cases, + struct stree **raw_stree) { - char *name = NULL; + char *name; struct symbol *sym; struct sm_state *sm; struct stree *true_states = NULL; @@ -728,6 +728,12 @@ struct stree *__implied_case_stree_rl(struct expression *switch_expr, name = expr_to_var_sym(switch_expr, &sym); if (!name || !sym) goto free; + + if (rl) + filter_top_rl(remaining_cases, rl_min(rl), rl_max(rl)); + else + rl = clone_rl(top_rl(*remaining_cases)); + sm = get_sm_state_stree(*raw_stree, SMATCH_EXTRA, name, sym); if (sm) separate_and_filter(sm, SPECIAL_EQUAL, rl, *raw_stree, &true_states, &false_states); @@ -746,28 +752,6 @@ free: return ret; } -struct stree *__implied_case_stree(struct expression *switch_expr, - struct expression *case_expr, - struct expression *case_to, - struct range_list_stack **remaining_cases, - struct stree **raw_stree) -{ - sval_t start, end; - struct range_list *rl = NULL; - - if (get_value(case_to, &end) && get_value(case_expr, &start)) { - filter_top_rl(remaining_cases, start, end); - add_range(&rl, start, end); - } else if (get_value(case_expr, &start)) { - filter_top_rl(remaining_cases, start, start); - add_range(&rl, start, start); - } else { - rl = clone_rl(top_rl(*remaining_cases)); - } - - return __implied_case_stree_rl(switch_expr, rl, remaining_cases, raw_stree); -} - static void match_end_func(struct symbol *sym) { if (__inline_fn) diff --git a/smatch_states.c b/smatch_states.c index cab10e24..1ce7ee0b 100644 --- a/smatch_states.c +++ b/smatch_states.c @@ -949,13 +949,13 @@ void __save_switch_states(struct expression *switch_expr) push_stree(&switch_stack, clone_stree(cur_stree)); } -void __merge_switches(struct expression *switch_expr, struct expression *case_expr, struct expression *case_to) +void __merge_switches(struct expression *switch_expr, struct range_list *case_rl) { struct stree *stree; struct stree *implied_stree; stree = pop_stree(&switch_stack); - implied_stree = __implied_case_stree(switch_expr, case_expr, case_to, &remaining_cases, &stree); + implied_stree = __implied_case_stree(switch_expr, case_rl, &remaining_cases, &stree); merge_stree(&cur_stree, implied_stree); free_stree(&implied_stree); push_stree(&switch_stack, stree); -- 2.11.4.GIT