Module Name: src
Committed By: rillig
Date: Tue Apr 19 20:08:52 UTC 2022
Modified Files:
src/tests/usr.bin/xlint/lint1: msg_298.c msg_298.exp
src/usr.bin/xlint/lint1: tree.c
Log Message:
lint: do not warn about converting (1234567L & 0xFF) to unsigned char
Due to the '& 0xFF', there is no possible loss of accuracy.
To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/tests/usr.bin/xlint/lint1/msg_298.c \
src/tests/usr.bin/xlint/lint1/msg_298.exp
cvs rdiff -u -r1.433 -r1.434 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_298.c
diff -u src/tests/usr.bin/xlint/lint1/msg_298.c:1.3 src/tests/usr.bin/xlint/lint1/msg_298.c:1.4
--- src/tests/usr.bin/xlint/lint1/msg_298.c:1.3 Tue Apr 19 19:56:29 2022
+++ src/tests/usr.bin/xlint/lint1/msg_298.c Tue Apr 19 20:08:52 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: msg_298.c,v 1.3 2022/04/19 19:56:29 rillig Exp $ */
+/* $NetBSD: msg_298.c,v 1.4 2022/04/19 20:08:52 rillig Exp $ */
# 3 "msg_298.c"
// Test for message: conversion from '%s' to '%s' may lose accuracy, arg #%d [298]
@@ -13,12 +13,10 @@ convert_bit_and(long l)
{
/* expect+1: warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298] */
take_uchar(l);
- /* expect+1: warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298] */
take_uchar(l & 0xFF);
/* expect+1: warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298] */
take_uchar(l & 0x100);
/* expect+1: warning: conversion from 'long' to 'signed char' may lose accuracy, arg #1 [298] */
take_schar(l & 0xFF);
- /* expect+1: warning: conversion from 'long' to 'signed char' may lose accuracy, arg #1 [298] */
take_schar(l & 0x7F);
}
Index: src/tests/usr.bin/xlint/lint1/msg_298.exp
diff -u src/tests/usr.bin/xlint/lint1/msg_298.exp:1.3 src/tests/usr.bin/xlint/lint1/msg_298.exp:1.4
--- src/tests/usr.bin/xlint/lint1/msg_298.exp:1.3 Tue Apr 19 19:56:29 2022
+++ src/tests/usr.bin/xlint/lint1/msg_298.exp Tue Apr 19 20:08:52 2022
@@ -1,5 +1,3 @@
msg_298.c(15): warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298]
-msg_298.c(17): warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298]
-msg_298.c(19): warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298]
-msg_298.c(21): warning: conversion from 'long' to 'signed char' may lose accuracy, arg #1 [298]
-msg_298.c(23): warning: conversion from 'long' to 'signed char' may lose accuracy, arg #1 [298]
+msg_298.c(18): warning: conversion from 'long' to 'unsigned char' may lose accuracy, arg #1 [298]
+msg_298.c(20): warning: conversion from 'long' to 'signed char' may lose accuracy, arg #1 [298]
Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.433 src/usr.bin/xlint/lint1/tree.c:1.434
--- src/usr.bin/xlint/lint1/tree.c:1.433 Sat Apr 16 22:21:10 2022
+++ src/usr.bin/xlint/lint1/tree.c Tue Apr 19 20:08:52 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: tree.c,v 1.433 2022/04/16 22:21:10 rillig Exp $ */
+/* $NetBSD: tree.c,v 1.434 2022/04/19 20:08:52 rillig Exp $ */
/*
* Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tree.c,v 1.433 2022/04/16 22:21:10 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.434 2022/04/19 20:08:52 rillig Exp $");
#endif
#include <float.h>
@@ -2176,6 +2176,37 @@ check_prototype_conversion(int arg, tspe
}
/*
+ * When converting a large integer type to a small integer type, in some
+ * cases the value of the actual expression is further restricted than the
+ * type bounds, such as in (expr & 0xFF) or (expr % 100) or (expr >> 24).
+ *
+ * See new_tnode, the '#if 0' code for SHR.
+ */
+static bool
+can_represent(const type_t *tp, const tnode_t *tn)
+{
+
+ if (tn->tn_op == BITAND) {
+ const tnode_t *rn = tn->tn_right;
+ tspec_t nt;
+
+ if (!(rn != NULL && rn->tn_op == CON &&
+ is_integer(rn->tn_type->t_tspec)))
+ return false;
+
+ uint64_t nmask = value_bits(size_in_bits(nt = tp->t_tspec));
+ if (!is_uinteger(nt))
+ nmask >>= 1;
+
+ uint64_t omask = (uint64_t)rn->tn_val->v_quad;
+ if ((omask & ~nmask) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/*
* Print warnings for conversions of integer types which may cause problems.
*/
static void
@@ -2214,6 +2245,7 @@ check_integer_conversion(op_t op, int ar
if (aflag > 0 &&
portable_size_in_bits(nt) < portable_size_in_bits(ot) &&
+ !can_represent(tp, tn) &&
(ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD ||
aflag > 1)) {
if (op == FARG) {