From 61ac8e557643a64da294d4ee333422c821f87c35 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 6 May 2020 17:55:43 +0300 Subject: [PATCH] bits: Fix handling of |= and &= Obviously |= and &= are very important so it's weird that it took so long to add this. The patch looks more complicated than I would have expected and I believe the reason for this is because it has tricky ordering with the modification hook. Signed-off-by: Dan Carpenter --- smatch_bits.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/smatch_bits.c b/smatch_bits.c index 21aa0775..5e310a13 100644 --- a/smatch_bits.c +++ b/smatch_bits.c @@ -128,10 +128,29 @@ static bool is_loop_iterator(struct expression *expr) return true; } +static bool handled_by_assign_hook(struct expression *expr) +{ + if (!expr || expr->type != EXPR_ASSIGNMENT) + return false; + if (__in_fake_assign) + return false; + if (is_loop_iterator(expr)) + return false; + + if (expr->op == '=' || + expr->op == SPECIAL_OR_ASSIGN || + expr->op == SPECIAL_AND_ASSIGN) + return true; + + return false; +} + static void match_modify(struct sm_state *sm, struct expression *mod_expr) { // FIXME: we really need to store the type + if (handled_by_assign_hook(mod_expr)) + return; set_state(my_id, sm->name, sm->sym, alloc_bstate(0, -1ULL)); } @@ -302,21 +321,29 @@ static void match_compare(struct expression *expr) static void match_assign(struct expression *expr) { - struct bit_info *binfo; + struct bit_info *start, *binfo; + struct smatch_state *new; - if (expr->op != '=') - return; - if (__in_fake_assign) - return; - if (is_loop_iterator(expr)) + if (!handled_by_assign_hook(expr)) return; binfo = get_bit_info(expr->right); if (!binfo) return; - if (is_unknown_binfo(get_type(expr->left), binfo)) - return; - set_state_expr(my_id, expr->left, alloc_bstate(binfo->set, binfo->possible)); + if (expr->op == '=') { + if (is_unknown_binfo(get_type(expr->left), binfo)) + return; + + set_state_expr(my_id, expr->left, alloc_bstate(binfo->set, binfo->possible)); + } else if (expr->op == SPECIAL_OR_ASSIGN) { + start = get_bit_info(expr->left); + new = alloc_bstate(start->set | binfo->set, start->possible | binfo->possible); + set_state_expr(my_id, expr->left, new); + } else if (expr->op == SPECIAL_AND_ASSIGN) { + start = get_bit_info(expr->left); + new = alloc_bstate(start->set & binfo->set, start->possible & binfo->possible); + set_state_expr(my_id, expr->left, new); + } } static void match_condition(struct expression *expr) -- 2.11.4.GIT