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;
}