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

Reply via email to