Module Name: src Committed By: rillig Date: Sat Oct 12 09:45:26 UTC 2024
Modified Files: src/tests/usr.bin/xlint/lint1: msg_132.c src/usr.bin/xlint/lint1: tree.c Log Message: lint: reduce wrong warnings about loss of accuracy in signed '%' To generate a diff of this commit: cvs rdiff -u -r1.45 -r1.46 src/tests/usr.bin/xlint/lint1/msg_132.c cvs rdiff -u -r1.655 -r1.656 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.45 src/tests/usr.bin/xlint/lint1/msg_132.c:1.46 --- src/tests/usr.bin/xlint/lint1/msg_132.c:1.45 Sat Oct 12 06:48:30 2024 +++ src/tests/usr.bin/xlint/lint1/msg_132.c Sat Oct 12 09:45:26 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_132.c,v 1.45 2024/10/12 06:48:30 rillig Exp $ */ +/* $NetBSD: msg_132.c,v 1.46 2024/10/12 09:45:26 rillig Exp $ */ # 3 "msg_132.c" // Test for message: conversion from '%s' to '%s' may lose accuracy [132] @@ -290,27 +290,16 @@ test_ic_mod(void) bits.u10 = u64 % 1000; u16 = u64 % 1000; - /* - * For signed division, if the result of 'a / b' is not representable - * exactly, the result of 'a % b' is defined such that - * '(a / b) * a + a % b == a'. - * - * If the result of 'a / b' is not representable exactly, the result - * 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] */ + /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ + s8 = s16 % s16; s8 = s64 % 1; + s8 = s64 % (s16 & 1); + /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ + s8 = s64 % (s16 & 0); + s8 = (s64 & 0x7f) % s64; + /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ + s8 = (s64 & 0xff) % s64; } void Index: src/usr.bin/xlint/lint1/tree.c diff -u src/usr.bin/xlint/lint1/tree.c:1.655 src/usr.bin/xlint/lint1/tree.c:1.656 --- src/usr.bin/xlint/lint1/tree.c:1.655 Fri Oct 11 20:45:15 2024 +++ src/usr.bin/xlint/lint1/tree.c Sat Oct 12 09:45:25 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: tree.c,v 1.655 2024/10/11 20:45:15 rillig Exp $ */ +/* $NetBSD: tree.c,v 1.656 2024/10/12 09:45:25 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.655 2024/10/11 20:45:15 rillig Exp $"); +__RCSID("$NetBSD: tree.c,v 1.656 2024/10/12 09:45:25 rillig Exp $"); #endif #include <float.h> @@ -59,6 +59,30 @@ typedef struct integer_constraints { } integer_constraints; +static int64_t +s64_min(int64_t a, int64_t b) +{ + return a < b ? a : b; +} + +static int64_t +s64_max(int64_t a, int64_t b) +{ + return a > b ? a : b; +} + +static uint64_t +s64_abs(int64_t x) +{ + return x >= 0 ? (uint64_t)x : -(uint64_t)x; +} + +static uint64_t +u64_max(uint64_t a, uint64_t b) +{ + return a > b ? a : b; +} + static uint64_t u64_fill_right(uint64_t x) { @@ -163,12 +187,28 @@ ic_div(const type_t *tp, integer_constra } static integer_constraints +ic_mod_signed(integer_constraints a, integer_constraints b) +{ + integer_constraints c; + + uint64_t max_abs_b = u64_max(s64_abs(b.smin), s64_abs(b.smax)); + if (max_abs_b >> 63 != 0 || max_abs_b == 0) + return a; + c.smin = s64_max(a.smin, -(int64_t)(max_abs_b - 1)); + c.smax = s64_min(a.smax, (int64_t)(max_abs_b - 1)); + c.umin = 0; + c.umax = UINT64_MAX; + c.bclr = 0; + return c; +} + +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); + return ic_mod_signed(a, b); c.smin = INT64_MIN; c.smax = INT64_MAX; @@ -235,6 +275,10 @@ ic_bitand(integer_constraints a, integer c.smax = INT64_MAX; c.umin = 0; c.umax = ~(a.bclr | b.bclr); + if (c.umax >> 63 == 0) { + c.smin = 0; + c.smax = (int64_t)c.umax; + } c.bclr = a.bclr | b.bclr; return c; }