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) {