Print this page
11506 smatch resync

*** 639,649 **** new_state = alloc_link_state(links); set_state(link_id, var, sym, new_state); } ! static void match_inc(struct sm_state *sm) { struct string_list *links; struct smatch_state *state, *new; struct compare_data *data; char *tmp; --- 639,649 ---- new_state = alloc_link_state(links); set_state(link_id, var, sym, new_state); } ! static void match_inc(struct sm_state *sm, bool preserve) { struct string_list *links; struct smatch_state *state, *new; struct compare_data *data; char *tmp;
*** 671,680 **** --- 671,682 ---- case SPECIAL_EQUAL: case SPECIAL_GTE: case SPECIAL_UNSIGNED_GTE: case '>': case SPECIAL_UNSIGNED_GT: + if (preserve) + break; new = alloc_compare_state( data->left, data->left_var, data->left_vsl, flip ? '<' : '>', data->right, data->right_var, data->right_vsl); set_state(compare_id, tmp, NULL, new);
*** 691,701 **** set_state(compare_id, tmp, NULL, &undefined); } } END_FOR_EACH_PTR(tmp); } ! static void match_dec(struct sm_state *sm) { struct string_list *links; struct smatch_state *state; char *tmp; --- 693,703 ---- set_state(compare_id, tmp, NULL, &undefined); } } END_FOR_EACH_PTR(tmp); } ! static void match_dec(struct sm_state *sm, bool preserve) { struct string_list *links; struct smatch_state *state; char *tmp;
*** 711,720 **** --- 713,725 ---- case '<': case SPECIAL_UNSIGNED_LT: { struct compare_data *data = state->data; struct smatch_state *new; + if (preserve) + break; + new = alloc_compare_state( data->left, data->left_var, data->left_vsl, '<', data->right, data->right_var, data->right_vsl); set_state(compare_id, tmp, NULL, new);
*** 724,747 **** set_state(compare_id, tmp, NULL, &undefined); } } END_FOR_EACH_PTR(tmp); } static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr) { /* * if (foo > bar) then ++foo is also > bar. */ if (!mod_expr) return; if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP) return; if (mod_expr->op == SPECIAL_INCREMENT) ! match_inc(sm); else if (mod_expr->op == SPECIAL_DECREMENT) ! match_dec(sm); } static int is_self_assign(struct expression *expr) { if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=') --- 729,790 ---- set_state(compare_id, tmp, NULL, &undefined); } } END_FOR_EACH_PTR(tmp); } + static void reset_sm(struct sm_state *sm) + { + struct string_list *links; + char *tmp; + + links = sm->state->data; + + FOR_EACH_PTR(links, tmp) { + set_state(compare_id, tmp, NULL, &undefined); + } END_FOR_EACH_PTR(tmp); + set_state(link_id, sm->name, sm->sym, &undefined); + } + + static bool match_add_sub_assign(struct sm_state *sm, struct expression *expr) + { + struct range_list *rl; + sval_t zero = { .type = &int_ctype }; + + if (!expr || expr->type != EXPR_ASSIGNMENT) + return false; + if (expr->op != SPECIAL_ADD_ASSIGN && expr->op != SPECIAL_SUB_ASSIGN) + return false; + + get_absolute_rl(expr->right, &rl); + if (sval_is_negative(rl_min(rl))) { + reset_sm(sm); + return false; + } + + if (expr->op == SPECIAL_ADD_ASSIGN) + match_inc(sm, rl_has_sval(rl, zero)); + else + match_dec(sm, rl_has_sval(rl, zero)); + return true; + } + static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr) { /* * if (foo > bar) then ++foo is also > bar. */ if (!mod_expr) return; + if (match_add_sub_assign(sm, mod_expr)) + return; if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP) return; if (mod_expr->op == SPECIAL_INCREMENT) ! match_inc(sm, false); else if (mod_expr->op == SPECIAL_DECREMENT) ! match_dec(sm, false); } static int is_self_assign(struct expression *expr) { if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
*** 749,776 **** return expr_equiv(expr->left, expr->right); } static void match_modify(struct sm_state *sm, struct expression *mod_expr) { - struct string_list *links; - char *tmp; - if (mod_expr && is_self_assign(mod_expr)) return; /* handled by match_inc_dec() */ if (mod_expr && ((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) && (mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT))) return; ! links = sm->state->data; ! ! FOR_EACH_PTR(links, tmp) { ! set_state(compare_id, tmp, NULL, &undefined); ! } END_FOR_EACH_PTR(tmp); ! set_state(link_id, sm->name, sm->sym, &undefined); } static void match_preop(struct expression *expr) { struct expression *parent; --- 792,814 ---- return expr_equiv(expr->left, expr->right); } static void match_modify(struct sm_state *sm, struct expression *mod_expr) { if (mod_expr && is_self_assign(mod_expr)) return; /* handled by match_inc_dec() */ if (mod_expr && ((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) && (mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT))) return; + if (mod_expr && mod_expr->type == EXPR_ASSIGNMENT && + (mod_expr->op == SPECIAL_ADD_ASSIGN || mod_expr->op == SPECIAL_SUB_ASSIGN)) + return; ! reset_sm(sm); } static void match_preop(struct expression *expr) { struct expression *parent;
*** 1602,1612 **** ret = flip_comparison(ret); return ret; } ! int get_comparison(struct expression *a, struct expression *b) { char *one = NULL; char *two = NULL; int ret = 0; --- 1640,1650 ---- ret = flip_comparison(ret); return ret; } ! static int get_comparison_helper(struct expression *a, struct expression *b, bool use_extra) { char *one = NULL; char *two = NULL; int ret = 0;
*** 1651,1665 **** free: free_string(one); free_string(two); ! if (!ret) return comparison_from_extra(a, b); return ret; } int possible_comparison(struct expression *a, int comparison, struct expression *b) { char *one = NULL; char *two = NULL; int ret = 0; --- 1689,1713 ---- free: free_string(one); free_string(two); ! if (!ret && use_extra) return comparison_from_extra(a, b); return ret; } + int get_comparison(struct expression *a, struct expression *b) + { + return get_comparison_helper(a, b, true); + } + + int get_comparison_no_extra(struct expression *a, struct expression *b) + { + return get_comparison_helper(a, b, false); + } + int possible_comparison(struct expression *a, int comparison, struct expression *b) { char *one = NULL; char *two = NULL; int ret = 0;
*** 2325,2335 **** char *p; if (!parse_comparison(&value, op)) return 0; ! snprintf(buf, sizeof(buf), value); p = buf; if (*p++ != '$') return 0; --- 2373,2383 ---- char *p; if (!parse_comparison(&value, op)) return 0; ! snprintf(buf, sizeof(buf), "%s", value); p = buf; if (*p++ != '$') return 0;
*** 2493,2502 **** --- 2541,2551 ---- } void register_comparison(int id) { compare_id = id; + set_dynamic_states(compare_id); add_hook(&save_start_states, AFTER_DEF_HOOK); add_unmatched_state_hook(compare_id, unmatched_comparison); add_pre_merge_hook(compare_id, &pre_merge_hook); add_merge_hook(compare_id, &merge_compare_states); add_hook(&free_data, AFTER_FUNC_HOOK);
*** 2513,2522 **** --- 2562,2573 ---- } void register_comparison_links(int id) { link_id = id; + db_ignore_states(link_id); + set_dynamic_states(link_id); add_merge_hook(link_id, &merge_links); add_modification_hook(link_id, &match_modify); add_modification_hook_late(link_id, match_inc_dec); add_member_info_callback(link_id, struct_member_callback);
*** 2529,2538 **** --- 2580,2590 ---- } void register_comparison_inc_dec_links(int id) { inc_dec_link_id = id; + set_dynamic_states(inc_dec_link_id); set_up_link_functions(inc_dec_id, inc_dec_link_id); } static void filter_by_sm(struct sm_state *sm, int op, struct state_list **true_stack,