From fe186f5d9bc4168cb2fdb6427dd997385e21f7c8 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 15 Apr 2009 17:56:04 +0300 Subject: [PATCH] Store the implications for return_implies_state() assignments. We already did this for conditional functions but we needed to do it for the new return implies state functions. foo = try_lock(); if (foo < 0) return; Signed-off-by: Dan Carpenter --- smatch_extra.h | 4 ++++ smatch_function_hooks.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ smatch_ranges.c | 17 ++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/smatch_extra.h b/smatch_extra.h index 25b21b4d..c8815d67 100644 --- a/smatch_extra.h +++ b/smatch_extra.h @@ -59,3 +59,7 @@ void function_comparison(int comparison, struct expression *expr, long long valu int true_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left); int false_comparison_range_lr(int comparison, struct data_range *var, struct data_range *val, int left); struct data_range *alloc_range(long long min, long long max); +void tack_on(struct range_list **list, struct data_range *drange); +int in_list_exact(struct range_list *list, struct data_range *drange); + +struct smatch_state *alloc_extra_state_range(long long min, long long max); diff --git a/smatch_function_hooks.c b/smatch_function_hooks.c index 655a4563..f25519c1 100644 --- a/smatch_function_hooks.c +++ b/smatch_function_hooks.c @@ -164,7 +164,64 @@ static void assign_condition_funcs(const char *fn, struct expression *expr, free_slist(&__fake_cond_false); free: free_string(var_name); +} + +static struct call_back_list *get_same_ranged_call_backs(struct call_back_list *list, + struct data_range *drange) +{ + struct call_back_list *ret = NULL; + struct fcall_back *tmp; + + FOR_EACH_PTR(list, tmp) { + if (tmp->range->min == drange->min && tmp->range->max == drange->max) + add_ptr_list(&ret, tmp); + } END_FOR_EACH_PTR(tmp); + return ret; +} + +static void assign_ranged_funcs(const char *fn, struct expression *expr, + struct call_back_list *call_backs) +{ + struct fcall_back *tmp; + struct sm_state *sm; + char *var_name; + struct symbol *sym; + struct smatch_state *extra_state; + struct state_list *final_states = NULL; + struct range_list *handled_ranges = NULL; + struct call_back_list *same_range_call_backs = NULL; + + var_name = get_variable_from_expr(expr->left, &sym); + if (!var_name || !sym) + goto free; + + __fake_cur = 1; + FOR_EACH_PTR(call_backs, tmp) { + if (tmp->type != RANGED_CALL) + continue; + if (in_list_exact(handled_ranges, tmp->range)) + continue; + tack_on(&handled_ranges, tmp->range); + + same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range); + call_call_backs(same_range_call_backs, RANGED_CALL, fn, expr->right); + __free_ptr_list((struct ptr_list **)&same_range_call_backs); + + extra_state = alloc_extra_state_range(tmp->range->min, tmp->range->max); + set_state(var_name, SMATCH_EXTRA, sym, extra_state); + merge_slist(&final_states, __fake_cur_slist); + free_slist(&__fake_cur_slist); + } END_FOR_EACH_PTR(tmp); + __fake_cur = 0; + + FOR_EACH_PTR(final_states, sm) { + __set_state(sm); + } END_FOR_EACH_PTR(sm); + + free_slist(&final_states); +free: + free_string(var_name); } void function_comparison(int comparison, struct expression *expr, long long value, int left) @@ -241,6 +298,7 @@ void __match_initializer_call(struct symbol *sym) e_assign->right = initializer; call_call_backs(call_backs, ASSIGN_CALL, fn, e_assign); assign_condition_funcs(fn, e_assign, call_backs); + assign_ranged_funcs(fn, e_assign, call_backs); } static void match_assign_call(struct expression *expr) @@ -256,6 +314,7 @@ static void match_assign_call(struct expression *expr) return; call_call_backs(call_backs, ASSIGN_CALL, fn, expr); assign_condition_funcs(fn, expr, call_backs); + assign_ranged_funcs(fn, expr, call_backs); } static void match_conditional_call(struct expression *expr) diff --git a/smatch_ranges.c b/smatch_ranges.c index 1c225d4b..6d02b391 100644 --- a/smatch_ranges.c +++ b/smatch_ranges.c @@ -418,6 +418,23 @@ int possibly_false(int comparison, struct data_info *dinfo, int num, int left) return ret; } +void tack_on(struct range_list **list, struct data_range *drange) +{ + add_ptr_list(list, drange); +} + +int in_list_exact(struct range_list *list, struct data_range *drange) +{ + struct data_range *tmp; + + FOR_EACH_PTR(list, tmp) { + if (tmp->min == drange->min && tmp->max == drange->max) + return 1; + } END_FOR_EACH_PTR(tmp); + return 0; + +} + static void free_single_dinfo(struct data_info *dinfo) { if (dinfo->type == DATA_RANGE) -- 2.11.4.GIT