Module Name:    src
Committed By:   rillig
Date:           Sun Jun  9 10:27:39 UTC 2024

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/tests/usr.bin/xlint/lint1: init_c99.c msg_259.c msg_298.c
            t_usage.sh
        src/usr.bin/xlint/lint1: err.c tree.c
Added Files:
        src/tests/usr.bin/xlint/lint1: msg_380.c msg_381.c

Log Message:
lint: warn about lossy floating point constant to integer conversions


To generate a diff of this commit:
cvs rdiff -u -r1.1318 -r1.1319 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/init_c99.c
cvs rdiff -u -r1.24 -r1.25 src/tests/usr.bin/xlint/lint1/msg_259.c
cvs rdiff -u -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/msg_298.c
cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/msg_380.c \
    src/tests/usr.bin/xlint/lint1/msg_381.c
cvs rdiff -u -r1.21 -r1.22 src/tests/usr.bin/xlint/lint1/t_usage.sh
cvs rdiff -u -r1.245 -r1.246 src/usr.bin/xlint/lint1/err.c
cvs rdiff -u -r1.645 -r1.646 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/distrib/sets/lists/tests/mi
diff -u src/distrib/sets/lists/tests/mi:1.1318 src/distrib/sets/lists/tests/mi:1.1319
--- src/distrib/sets/lists/tests/mi:1.1318	Sat Jun  8 13:50:47 2024
+++ src/distrib/sets/lists/tests/mi	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1318 2024/06/08 13:50:47 rillig Exp $
+# $NetBSD: mi,v 1.1319 2024/06/09 10:27:39 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -7515,6 +7515,8 @@
 ./usr/tests/usr.bin/xlint/lint1/msg_377.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_378.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/msg_379.c			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_380.c			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/msg_381.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/op_colon.c			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/op_colon.exp			tests-obsolete		obsolete,atf
 ./usr/tests/usr.bin/xlint/lint1/op_shl_lp64.c			tests-usr.bin-tests	compattestfile,atf

Index: src/tests/usr.bin/xlint/lint1/init_c99.c
diff -u src/tests/usr.bin/xlint/lint1/init_c99.c:1.1 src/tests/usr.bin/xlint/lint1/init_c99.c:1.2
--- src/tests/usr.bin/xlint/lint1/init_c99.c:1.1	Sat Jun  8 13:50:47 2024
+++ src/tests/usr.bin/xlint/lint1/init_c99.c	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: init_c99.c,v 1.1 2024/06/08 13:50:47 rillig Exp $	*/
+/*	$NetBSD: init_c99.c,v 1.2 2024/06/09 10:27:39 rillig Exp $	*/
 # 3 "init_c99.c"
 
 // Tests for initialization in C99 or later, mainly for designators.
@@ -290,6 +290,7 @@ struct ten ten = {
  * covering all tricky edge cases.
  */
 
+/* expect+1: warning: lossy conversion of 3.5 to 'int' [381] */
 int c99_6_7_8_p24_example1_i = 3.5;
 double _Complex c99_6_7_8_p24_example1_c = 5 + 3 * 1.0fi;
 

Index: src/tests/usr.bin/xlint/lint1/msg_259.c
diff -u src/tests/usr.bin/xlint/lint1/msg_259.c:1.24 src/tests/usr.bin/xlint/lint1/msg_259.c:1.25
--- src/tests/usr.bin/xlint/lint1/msg_259.c:1.24	Sat Jun  8 13:50:47 2024
+++ src/tests/usr.bin/xlint/lint1/msg_259.c	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_259.c,v 1.24 2024/06/08 13:50:47 rillig Exp $	*/
+/*	$NetBSD: msg_259.c,v 1.25 2024/06/09 10:27:39 rillig Exp $	*/
 # 3 "msg_259.c"
 
 // Test for message: argument %d is converted from '%s' to '%s' due to prototype [259]
@@ -236,7 +236,8 @@ constants(void)
 	/* expect+2: warning: argument 1 is converted from 'long long' to 'unsigned int' due to prototype [259] */
 	/* expect+1: warning: conversion of 'long long' to 'unsigned int' is out of range, arg #1 [295] */
 	unsigned_int(0x7fffffffffffffffLL);
-	/* expect+1: warning: argument 1 is converted from 'double' to 'unsigned int' due to prototype [259] */
+	/* expect+2: warning: argument 1 is converted from 'double' to 'unsigned int' due to prototype [259] */
+	/* expect+1: warning: lossy conversion of 2.1 to 'unsigned int', arg #1 [380] */
 	unsigned_int(2.1);
 }
 

Index: src/tests/usr.bin/xlint/lint1/msg_298.c
diff -u src/tests/usr.bin/xlint/lint1/msg_298.c:1.6 src/tests/usr.bin/xlint/lint1/msg_298.c:1.7
--- src/tests/usr.bin/xlint/lint1/msg_298.c:1.6	Sat Jun  8 13:50:47 2024
+++ src/tests/usr.bin/xlint/lint1/msg_298.c	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_298.c,v 1.6 2024/06/08 13:50:47 rillig Exp $	*/
+/*	$NetBSD: msg_298.c,v 1.7 2024/06/09 10:27:39 rillig Exp $	*/
 # 3 "msg_298.c"
 
 // Test for message: conversion from '%s' to '%s' may lose accuracy, arg #%d [298]
@@ -22,9 +22,4 @@ convert_bit_and(long l)
 	take_schar(l & 0x7F);
 }
 
-void
-convert_floating_to_integer(void)
-{
-	// TODO: warn about lossy conversion.
-	take_uint(2.1);
-}
+// For lossy floating-to-integer conversions, see messages 380 and 381.

Index: src/tests/usr.bin/xlint/lint1/t_usage.sh
diff -u src/tests/usr.bin/xlint/lint1/t_usage.sh:1.21 src/tests/usr.bin/xlint/lint1/t_usage.sh:1.22
--- src/tests/usr.bin/xlint/lint1/t_usage.sh:1.21	Sat May 11 15:53:38 2024
+++ src/tests/usr.bin/xlint/lint1/t_usage.sh	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-# $NetBSD: t_usage.sh,v 1.21 2024/05/11 15:53:38 rillig Exp $
+# $NetBSD: t_usage.sh,v 1.22 2024/06/09 10:27:39 rillig Exp $
 #
 # Copyright (c) 2023 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -39,13 +39,13 @@ suppress_messages_body()
 
 	# The largest known message.
 	atf_check \
-	    "$lint1" -X 379 code.c /dev/null
+	    "$lint1" -X 381 code.c /dev/null
 
 	# Larger than the largest known message.
 	atf_check \
 	    -s 'exit:1' \
-	    -e "inline:lint1: invalid message ID '380'\n" \
-	    "$lint1" -X 380 code.c /dev/null
+	    -e "inline:lint1: invalid message ID '382'\n" \
+	    "$lint1" -X 382 code.c /dev/null
 
 	# Whitespace is not allowed before a message ID.
 	atf_check \

Index: src/usr.bin/xlint/lint1/err.c
diff -u src/usr.bin/xlint/lint1/err.c:1.245 src/usr.bin/xlint/lint1/err.c:1.246
--- src/usr.bin/xlint/lint1/err.c:1.245	Sat Jun  8 06:37:06 2024
+++ src/usr.bin/xlint/lint1/err.c	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: err.c,v 1.245 2024/06/08 06:37:06 rillig Exp $	*/
+/*	$NetBSD: err.c,v 1.246 2024/06/09 10:27:39 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID)
-__RCSID("$NetBSD: err.c,v 1.245 2024/06/08 06:37:06 rillig Exp $");
+__RCSID("$NetBSD: err.c,v 1.246 2024/06/09 10:27:39 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -435,6 +435,8 @@ static const char *const msgs[] = {
 	"redundant '\\0' at the end of the format",			// 377
 	"conversion '%.*s' is unreachable by input value",		// 378
 	"comparing integer '%s' to floating point constant %Lg",	// 379
+	"lossy conversion of %Lg to '%s', arg #%d",			// 380
+	"lossy conversion of %Lg to '%s'",				// 381
 };
 
 static bool is_suppressed[sizeof(msgs) / sizeof(msgs[0])];

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.645 src/usr.bin/xlint/lint1/tree.c:1.646
--- src/usr.bin/xlint/lint1/tree.c:1.645	Sat Jun  8 11:55:40 2024
+++ src/usr.bin/xlint/lint1/tree.c	Sun Jun  9 10:27:39 2024
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.645 2024/06/08 11:55:40 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.646 2024/06/09 10:27:39 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.645 2024/06/08 11:55:40 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.646 2024/06/09 10:27:39 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -3289,7 +3289,26 @@ promote(op_t op, bool farg, tnode_t *tn)
 }
 
 static void
-convert_integer_from_floating(op_t op, const type_t *tp, const tnode_t *tn)
+check_lossy_floating_to_integer_conversion(
+    op_t op, int arg, const type_t *tp, const tnode_t *tn)
+{
+	long double x = tn->u.value.u.floating;
+	integer_constraints ic = ic_any(tp);
+	if (is_uinteger(tp->t_tspec)
+	    ? x >= ic.umin && x <= ic.umax && x == (uint64_t)x
+	    : x >= ic.smin && x <= ic.smax && x == (int64_t)x)
+		return;
+	if (op == FARG)
+		/* lossy conversion of %Lg to '%s', arg #%d */
+		warning(380, x, type_name(tp), arg);
+	else
+		/* lossy conversion of %Lg to '%s' */
+		warning(381, x, type_name(tp));
+}
+
+static void
+convert_integer_from_floating(
+    op_t op, int arg, const type_t *tp, const tnode_t *tn)
 {
 
 	if (op == CVT)
@@ -3298,6 +3317,8 @@ convert_integer_from_floating(op_t op, c
 	else
 		/* implicit conversion from floating point '%s' to ... */
 		query_message(1, type_name(tn->tn_type), type_name(tp));
+	if (tn->tn_op == CON)
+		check_lossy_floating_to_integer_conversion(op, arg, tp, tn);
 }
 
 static bool
@@ -3649,7 +3670,7 @@ convert(op_t op, int arg, type_t *tp, tn
 		} else if (is_integer(ot))
 			convert_integer_from_integer(op, arg, nt, ot, tp, tn);
 		else if (is_floating(ot))
-			convert_integer_from_floating(op, tp, tn);
+			convert_integer_from_floating(op, arg, tp, tn);
 		else if (ot == PTR)
 			convert_integer_from_pointer(op, nt, tp, tn);
 
@@ -3731,12 +3752,15 @@ convert_constant_from_floating(op_t op, 
 		lint_assert(nt != LDOUBLE);
 		const char *ot_name = type_name(gettyp(ov->v_tspec));
 		const char *nt_name = type_name(ntp);
+		if (is_integer(nt))
+			goto after_warning;
 		if (op == FARG)
 			/* conversion of '%s' to '%s' is out of range, ... */
 			warning(295, ot_name, nt_name, arg);
 		else
 			/* conversion of '%s' to '%s' is out of range */
 			warning(119, ot_name, nt_name);
+	after_warning:
 		ov->u.floating = ov->u.floating > 0 ? max : min;
 	}
 

Added files:

Index: src/tests/usr.bin/xlint/lint1/msg_380.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_380.c:1.1
--- /dev/null	Sun Jun  9 10:27:39 2024
+++ src/tests/usr.bin/xlint/lint1/msg_380.c	Sun Jun  9 10:27:39 2024
@@ -0,0 +1,60 @@
+/*	$NetBSD: msg_380.c,v 1.1 2024/06/09 10:27:39 rillig Exp $	*/
+# 3 "msg_380.c"
+
+// Test for message: lossy conversion of %Lg to '%s', arg #%d [380]
+
+/* lint1-extra-flags: -X 351 */
+
+void take_s32(int);
+void take_u32(unsigned int);
+void take_s64(long long);
+void take_u64(unsigned long long);
+
+void
+conversions(void)
+{
+	/* expect+1: warning: lossy conversion of -2.14748e+09 to 'int', arg #1 [380] */
+	take_s32(-2147483649.0);
+	take_s32(-2147483648.0);
+	/* expect+1: warning: lossy conversion of 3.141 to 'int', arg #1 [380] */
+	take_s32(3.141);
+	take_s32(2147483647.0);
+	/* expect+1: warning: lossy conversion of 2.14748e+09 to 'int', arg #1 [380] */
+	take_s32(2147483648.0);
+
+	/* expect+1: warning: lossy conversion of -1 to 'unsigned int', arg #1 [380] */
+	take_u32(-1.0);
+	take_u32(-0.0);
+	take_u32(0.0);
+	/* expect+1: warning: lossy conversion of 3.141 to 'unsigned int', arg #1 [380] */
+	take_u32(3.141);
+	take_u32(4294967295.0);
+	/* expect+1: warning: lossy conversion of 4.29497e+09 to 'unsigned int', arg #1 [380] */
+	take_u32(4294967296.0);
+
+	/* expect+1: warning: lossy conversion of -9.22337e+18 to 'long long', arg #1 [380] */
+	take_s64(-9223372036854776833.0);
+	/* The constant ...809 is rounded down to ...808, thus no warning. */
+	take_s64(-9223372036854775809.0);
+	take_s64(-9223372036854775808.0);
+	/* expect+1: warning: lossy conversion of 3.141 to 'long long', arg #1 [380] */
+	take_s64(3.141);
+	/* expect+1: warning: lossy conversion of 9.22337e+18 to 'long long', arg #1 [380] */
+	take_s64(9223372036854775807.0);
+	/* expect+1: warning: lossy conversion of 9.22337e+18 to 'long long', arg #1 [380] */
+	take_s64(9223372036854775808.0);
+
+	/* expect+1: warning: lossy conversion of -1 to 'unsigned long long', arg #1 [380] */
+	take_u64(-1.0);
+	take_u64(-0.0);
+	take_u64(0.0);
+	/* expect+1: warning: lossy conversion of 3.141 to 'unsigned long long', arg #1 [380] */
+	take_u64(3.141);
+	take_u64(18446744073709550591.0);
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long', arg #1 [380] */
+	take_u64(18446744073709550592.0);
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long', arg #1 [380] */
+	take_u64(18446744073709551615.0);
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long', arg #1 [380] */
+	take_u64(18446744073709551616.0);
+}
Index: src/tests/usr.bin/xlint/lint1/msg_381.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_381.c:1.1
--- /dev/null	Sun Jun  9 10:27:39 2024
+++ src/tests/usr.bin/xlint/lint1/msg_381.c	Sun Jun  9 10:27:39 2024
@@ -0,0 +1,60 @@
+/*	$NetBSD: msg_381.c,v 1.1 2024/06/09 10:27:39 rillig Exp $	*/
+# 3 "msg_381.c"
+
+// Test for message: lossy conversion of %Lg to '%s' [381]
+
+/* lint1-extra-flags: -X 351 */
+
+int s32;
+unsigned int u32;
+long long s64;
+unsigned long long u64;
+
+void
+conversions(void)
+{
+	/* expect+1: warning: lossy conversion of -2.14748e+09 to 'int' [381] */
+	s32 = -2147483649.0;
+	s32 = -2147483648.0;
+	/* expect+1: warning: lossy conversion of 3.141 to 'int' [381] */
+	s32 = 3.141;
+	s32 = 2147483647.0;
+	/* expect+1: warning: lossy conversion of 2.14748e+09 to 'int' [381] */
+	s32 = 2147483648.0;
+
+	/* expect+1: warning: lossy conversion of -1 to 'unsigned int' [381] */
+	u32 = -1.0;
+	u32 = -0.0;
+	u32 = 0.0;
+	/* expect+1: warning: lossy conversion of 3.141 to 'unsigned int' [381] */
+	u32 = 3.141;
+	u32 = 4294967295.0;
+	/* expect+1: warning: lossy conversion of 4.29497e+09 to 'unsigned int' [381] */
+	u32 = 4294967296.0;
+
+	/* expect+1: warning: lossy conversion of -9.22337e+18 to 'long long' [381] */
+	s64 = -9223372036854776833.0;
+	/* The constant ...809 is rounded down to ...808, thus no warning. */
+	s64 = -9223372036854775809.0;
+	s64 = -9223372036854775808.0;
+	/* expect+1: warning: lossy conversion of 3.141 to 'long long' [381] */
+	s64 = 3.141;
+	/* expect+1: warning: lossy conversion of 9.22337e+18 to 'long long' [381] */
+	s64 = 9223372036854775807.0;
+	/* expect+1: warning: lossy conversion of 9.22337e+18 to 'long long' [381] */
+	s64 = 9223372036854775808.0;
+
+	/* expect+1: warning: lossy conversion of -1 to 'unsigned long long' [381] */
+	u64 = -1.0;
+	u64 = -0.0;
+	u64 = 0.0;
+	/* expect+1: warning: lossy conversion of 3.141 to 'unsigned long long' [381] */
+	u64 = 3.141;
+	u64 = 18446744073709550591.0;
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long' [381] */
+	u64 = 18446744073709550592.0;
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long' [381] */
+	u64 = 18446744073709551615.0;
+	/* expect+1: warning: lossy conversion of 1.84467e+19 to 'unsigned long long' [381] */
+	u64 = 18446744073709551616.0;
+}

Reply via email to