Module Name: src Committed By: rillig Date: Wed Jul 6 21:59:07 UTC 2022
Modified Files: src/tests/usr.bin/xlint/lint1: msg_132.c Log Message: tests/lint: test 'may lose accuracy' for '%' For unsigned integers, the possible range of the result can be narrowed down by looking at the right operand of the '%'. Right now, lint doesn't do this though. To generate a diff of this commit: cvs rdiff -u -r1.21 -r1.22 src/tests/usr.bin/xlint/lint1/msg_132.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.21 src/tests/usr.bin/xlint/lint1/msg_132.c:1.22 --- src/tests/usr.bin/xlint/lint1/msg_132.c:1.21 Sun Jul 3 14:35:54 2022 +++ src/tests/usr.bin/xlint/lint1/msg_132.c Wed Jul 6 21:59:06 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_132.c,v 1.21 2022/07/03 14:35:54 rillig Exp $ */ +/* $NetBSD: msg_132.c,v 1.22 2022/07/06 21:59:06 rillig Exp $ */ # 3 "msg_132.c" // Test for message: conversion from '%s' to '%s' may lose accuracy [132] @@ -22,6 +22,7 @@ typedef signed short s16_t; typedef signed int s32_t; typedef signed long long s64_t; + u8_t u8; u16_t u16; u32_t u32; @@ -32,6 +33,23 @@ s16_t s16; s32_t s32; s64_t s64; +struct bit_fields { + unsigned u1:1; + unsigned u2:2; + unsigned u3:3; + unsigned u4:4; + unsigned u5:5; + unsigned u6:6; + unsigned u7:7; + unsigned u8:8; + unsigned u9:9; + unsigned u10:10; + unsigned u11:11; + unsigned u12:12; + unsigned u32:32; +} bits; + + void unsigned_to_unsigned(void) { @@ -223,26 +241,27 @@ test_ic_shr(u64_t x) return x; } - -struct bit_fields { - unsigned bits_32: 32; - unsigned bits_5: 5; - unsigned bits_3: 3; -}; - unsigned char -test_bit_fields(struct bit_fields s, unsigned long long m) +test_bit_fields(unsigned long long m) { /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned int:3' may lose accuracy [132] */ - s.bits_3 = s.bits_32 & m; + bits.u3 = bits.u32 & m; - s.bits_5 = s.bits_3 & m; - s.bits_32 = s.bits_5 & m; + bits.u5 = bits.u3 & m; + bits.u32 = bits.u5 & m; /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned char' may lose accuracy [132] */ - return s.bits_32 & m; + return bits.u32 & m; } +/* + * Traditional C has an extra rule that the right-hand operand of a bit shift + * operator is converted to 'int'. Before tree.c 1.467 from 2022-07-02, this + * conversion was implemented as a CVT node, which means a cast, not an + * implicit conversion. Changing the CVT to NOOP would have caused a wrong + * warning 'may lose accuracy' in language levels other than traditional C. + */ + u64_t u64_shl(u64_t lhs, u64_t rhs) { @@ -266,3 +285,32 @@ s64_shr(s64_t lhs, s64_t rhs) { return lhs >> rhs; } + +void +test_ic_mod(void) +{ + /* The result is between 0 and 254. */ + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ + u8 = u64 % u8; + + /* The result is between 0 and 1000. */ + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ + u8 = u64 % 1000; + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */ + u16 = u64 % 1000; + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */ + bits.u9 = u64 % 1000; + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:10' may lose accuracy [132] */ + bits.u10 = 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. + * + * C90 6.3.5, C99 6.5.5. + */ +}