Module Name: src Committed By: rillig Date: Wed Jul 6 22:26:31 UTC 2022
Modified Files: src/tests/usr.bin/xlint/lint1: msg_132.c src/usr.bin/xlint/lint1: tree.c Log Message: lint: do not warn about 'may lose accuracy' in safe cases of '%' The possible values of the expression 'a % b' for unsigned integers lie between 0 and (b - 1). For signed integers, it's more complicated, so ignore them for now. To generate a diff of this commit: cvs rdiff -u -r1.22 -r1.23 src/tests/usr.bin/xlint/lint1/msg_132.c cvs rdiff -u -r1.471 -r1.472 src/usr.bin/xlint/lint1/tree.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/tests/usr.bin/xlint/lint1/msg_132.c diff -u src/tests/usr.bin/xlint/lint1/msg_132.c:1.22 src/tests/usr.bin/xlint/lint1/msg_132.c:1.23 --- src/tests/usr.bin/xlint/lint1/msg_132.c:1.22 Wed Jul 6 21:59:06 2022 +++ src/tests/usr.bin/xlint/lint1/msg_132.c Wed Jul 6 22:26:31 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_132.c,v 1.22 2022/07/06 21:59:06 rillig Exp $ */ +/* $NetBSD: msg_132.c,v 1.23 2022/07/06 22:26:31 rillig Exp $ */ # 3 "msg_132.c" // Test for message: conversion from '%s' to '%s' may lose accuracy [132] @@ -290,18 +290,22 @@ void test_ic_mod(void) { /* The result is between 0 and 254. */ - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ u8 = u64 % u8; + /* The result is between 0 and 255. */ + u8 = u64 % 256; + + /* The result is between 0 and 256. */ + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ + u8 = u64 % 257; + /* The result is between 0 and 1000. */ /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ u8 = u64 % 1000; - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */ - u16 = u64 % 1000; /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */ bits.u9 = u64 % 1000; - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:10' may lose accuracy [132] */ bits.u10 = u64 % 1000; + u16 = u64 % 1000; /* * For signed division, if the result of 'a / b' is not representable @@ -309,8 +313,19 @@ test_ic_mod(void) * '(a / b) * a + a % b == a'. * * If the result of 'a / b' is not representable exactly, the result - * of 'a % b' is not defined. + * of 'a % b' is not defined. Due to this uncertainty, lint does not + * narrow down the range for signed modulo expressions. * * C90 6.3.5, C99 6.5.5. */ + + /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ + s8 = s16 % s8; + + /* + * The result is always 0, it's a theoretical edge case though, so + * lint doesn't care to implement this. + */ + /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ + s8 = s64 % 1; } Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.471 src/usr.bin/xlint/lint1/tree.c:1.472 --- src/usr.bin/xlint/lint1/tree.c:1.471 Tue Jul 5 22:50:41 2022 +++ src/usr.bin/xlint/lint1/tree.c Wed Jul 6 22:26:30 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.471 2022/07/05 22:50:41 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.472 2022/07/06 22:26:30 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tree.c,v 1.471 2022/07/05 22:50:41 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.472 2022/07/06 22:26:30 rillig Exp $"); #endif #include <float.h> @@ -104,6 +104,18 @@ static void check_precedence_confusion(t extern sig_atomic_t fpe; +static uint64_t +u64_fill_right(uint64_t x) +{ + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + return x; +} + static bool ic_maybe_signed(const type_t *tp, const integer_constraints *ic) { @@ -200,6 +212,23 @@ ic_bitor(integer_constraints a, integer_ } static integer_constraints +ic_mod(const type_t *tp, integer_constraints a, integer_constraints b) +{ + integer_constraints c; + + if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)) + return ic_any(tp); + + c.smin = INT64_MIN; + c.smax = INT64_MAX; + c.umin = 0; + c.umax = b.umax - 1; + c.bset = 0; + c.bclr = ~u64_fill_right(c.umax); + return c; +} + +static integer_constraints ic_shl(const type_t *tp, integer_constraints a, integer_constraints b) { integer_constraints c; @@ -264,6 +293,10 @@ ic_expr(const tnode_t *tn) return ic_any(tn->tn_type); lc = ic_expr(tn->tn_left); return ic_cvt(tn->tn_type, tn->tn_left->tn_type, lc); + case MOD: + lc = ic_expr(before_conversion(tn->tn_left)); + rc = ic_expr(before_conversion(tn->tn_right)); + return ic_mod(tn->tn_type, lc, rc); case SHL: lc = ic_expr(tn->tn_left); rc = ic_expr(tn->tn_right);