Module Name:    src
Committed By:   rillig
Date:           Wed Jan  1 14:09:28 UTC 2025

Modified Files:
        src/tests/usr.bin/xlint/lint1: msg_132.c
        src/usr.bin/xlint/lint1: tree.c

Log Message:
lint: fix wrong warning about possible loss of accuracy

The expression "'0' + random() % 10" always fits in a signed or unsigned
char.


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/tests/usr.bin/xlint/lint1/msg_132.c
cvs rdiff -u -r1.664 -r1.665 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.47 src/tests/usr.bin/xlint/lint1/msg_132.c:1.48
--- src/tests/usr.bin/xlint/lint1/msg_132.c:1.47	Wed Jan  1 14:03:42 2025
+++ src/tests/usr.bin/xlint/lint1/msg_132.c	Wed Jan  1 14:09:28 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_132.c,v 1.47 2025/01/01 14:03:42 rillig Exp $	*/
+/*	$NetBSD: msg_132.c,v 1.48 2025/01/01 14:09:28 rillig Exp $	*/
 # 3 "msg_132.c"
 
 // Test for message: conversion from '%s' to '%s' may lose accuracy [132]
@@ -307,9 +307,7 @@ test_ic_plus(void)
 {
 	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
 	s8 = -129 + s64 % 1;
-	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
 	s8 = -128 + s64 % 1;
-	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
 	s8 = 127 + s64 % 1;
 	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
 	s8 = 128 + s64 % 1;
@@ -320,19 +318,15 @@ test_ic_plus(void)
 	/* expect+2: warning: conversion of negative constant -128 to unsigned type 'unsigned long long' [222] */
 	/* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
 	s8 = -128 + u64 % 1;
-	/* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
 	s8 = 127 + u64 % 1;
 	/* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
 	s8 = 128 + u64 % 1;
 
-	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
 	u8 = 0 + u64 % 1;
-	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
 	u8 = 255 + u64 % 1;
 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
 	u8 = 256 + u64 % 1;
 
-	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
 	s8 = '0' + s64 % 10;
 }
 

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.664 src/usr.bin/xlint/lint1/tree.c:1.665
--- src/usr.bin/xlint/lint1/tree.c:1.664	Sun Dec 15 06:04:17 2024
+++ src/usr.bin/xlint/lint1/tree.c	Wed Jan  1 14:09:28 2025
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.664 2024/12/15 06:04:17 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.665 2025/01/01 14:09:28 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.664 2024/12/15 06:04:17 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.665 2025/01/01 14:09:28 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -83,6 +83,45 @@ u64_max(uint64_t a, uint64_t b)
 	return a > b ? a : b;
 }
 
+static int64_t
+si_min_value(const type_t *tp)
+{
+	uint64_t mask = value_bits(size_in_bits(tp->t_tspec));
+	return -(int64_t)(mask >> 1) - 1;
+}
+
+static int64_t
+si_max_value(const type_t *tp)
+{
+	uint64_t mask = value_bits(size_in_bits(tp->t_tspec));
+	return (int64_t)(mask >> 1);
+}
+
+static uint64_t
+ui_max_value(const type_t *tp)
+{
+	return value_bits(size_in_bits(tp->t_tspec));
+}
+
+static int64_t
+si_plus_sat(const type_t *tp, int64_t a, int64_t b)
+{
+	if (a >= 0) {
+		int64_t max = si_max_value(tp);
+		return b <= max - a ? a + b : max;
+	} else {
+		int64_t min = si_min_value(tp);
+		return b >= min - a ? a + b : min;
+	}
+}
+
+static uint64_t
+ui_plus_sat(const type_t *tp, uint64_t a, uint64_t b)
+{
+	uint64_t max = ui_max_value(tp);
+	return b <= max - a ? a + b : max;
+}
+
 static uint64_t
 u64_fill_right(uint64_t x)
 {
@@ -219,6 +258,20 @@ ic_mod(const type_t *tp, integer_constra
 }
 
 static integer_constraints
+ic_plus(const type_t *tp, integer_constraints a, integer_constraints b)
+{
+	bool maybe_signed = ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b);
+
+	integer_constraints c;
+	c.smin = maybe_signed ? si_plus_sat(tp, a.smin, b.smin) : INT64_MIN;
+	c.smax = maybe_signed ? si_plus_sat(tp, a.smax, b.smax) : INT64_MAX;
+	c.umin = maybe_signed ? 0 : ui_plus_sat(tp, a.umin, b.umin);
+	c.umax = maybe_signed ? UINT64_MAX : ui_plus_sat(tp, a.umax, b.umax);
+	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;
@@ -360,6 +413,10 @@ ic_expr(const tnode_t *tn)
 		lc = ic_expr(before_conversion(tn->u.ops.left));
 		rc = ic_expr(before_conversion(tn->u.ops.right));
 		return ic_mod(tn->tn_type, lc, rc);
+	case PLUS:
+		lc = ic_expr(before_conversion(tn->u.ops.left));
+		rc = ic_expr(before_conversion(tn->u.ops.right));
+		return ic_plus(tn->tn_type, lc, rc);
 	case SHL:
 		lc = ic_expr(tn->u.ops.left);
 		rc = ic_expr(tn->u.ops.right);

Reply via email to