The handle_bit_test condition wasn't setting a false range_list for the false state and hence the implied rl was coming out to be false. The false and true rls have been calculating using rl_intersection and rl_filter commands. Signed-off-by: Harshvardhan Jha <harshvardhan.jha@xxxxxxxxxx> --- smatch_extra.c | 17 +++++++++-------- validation/sm_bits2.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 validation/sm_bits2.c diff --git a/smatch_extra.c b/smatch_extra.c index e864646a..27bf5a02 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -2061,7 +2061,7 @@ static void match_comparison(struct expression *expr) static bool handle_bit_test(struct expression *expr) { - struct range_list *orig_rl, *rl; + struct range_list *orig_rl, *rl, *true_rl, *false_rl; struct expression *shift, *mask, *var; struct bit_info *bit_info; sval_t sval; @@ -2083,23 +2083,24 @@ static bool handle_bit_test(struct expression *expr) bit_info = get_bit_info(mask); if (!bit_info) return false; - if (!bit_info->possible) + if (!bit_info->possible){ + set_true_false_states_expr(my_id, var, alloc_estate_empty(), NULL); return false; + } get_absolute_rl(var, &orig_rl); if (sval_is_negative(rl_min(orig_rl)) || rl_max(orig_rl).uvalue > type_bits(get_type(shift->left))) return false; - low.value = ffsll(bit_info->possible); - high.value = sm_fls64(bit_info->possible); + low.value = ffsll(bit_info->possible) - 1; + high.value = sm_fls64(bit_info->possible) - 1; rl = alloc_rl(low, high); rl = cast_rl(get_type(var), rl); - rl = rl_intersection(orig_rl, rl); - if (!rl) - return false; + true_rl = rl_intersection(orig_rl, rl); + false_rl = rl_filter(orig_rl, rl); - set_extra_expr_true_false(shift->right, alloc_estate_rl(rl), NULL); + set_extra_expr_true_false(shift->right, alloc_estate_rl(true_rl), alloc_estate_rl(false_rl)); return true; } diff --git a/validation/sm_bits2.c b/validation/sm_bits2.c new file mode 100644 index 00000000..1a43538a --- /dev/null +++ b/validation/sm_bits2.c @@ -0,0 +1,28 @@ +#include "../check_debug.h" + +unsigned int frob(); + +void test(void) +{ + unsigned int mask = 0xff0; + unsigned int x = frob(); + + if (x < 4 || x > 11) + return; + + if ((1 << x) & mask) { + __smatch_implied(x); + return; + } + __smatch_implied(x); +} + +/* + * check-name: smatch bits 2 + * check-command: smatch sm_bits2.c + * + * check-output-start +sm_bits2.c:14 test() implied: x = '4-11' +sm_bits2.c:17 test() implied: x = '' + * check-output-end + */ -- 2.32.0