Module Name: src Committed By: rillig Date: Sat Oct 12 06:48:30 UTC 2024
Modified Files: src/tests/usr.bin/xlint/lint1: msg_132.c Log Message: tests/lint: extend test for integer constraints To generate a diff of this commit: cvs rdiff -u -r1.44 -r1.45 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.44 src/tests/usr.bin/xlint/lint1/msg_132.c:1.45 --- src/tests/usr.bin/xlint/lint1/msg_132.c:1.44 Tue Oct 8 19:50:49 2024 +++ src/tests/usr.bin/xlint/lint1/msg_132.c Sat Oct 12 06:48:30 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_132.c,v 1.44 2024/10/08 19:50:49 rillig Exp $ */ +/* $NetBSD: msg_132.c,v 1.45 2024/10/12 06:48:30 rillig Exp $ */ # 3 "msg_132.c" // Test for message: conversion from '%s' to '%s' may lose accuracy [132] @@ -206,36 +206,39 @@ non_constant_expression(void) * Since tree.c 1.444 from 2022-05-26, lint tracks simple bitwise and * arithmetic constraints across a single expression. */ -static inline u16_t -be16dec(const void *buf) +void +be16dec(void) { - const u8_t *p = buf; - /* * Before tree.c 1.444 from 2022-05-26, lint complained that the * conversion from 'int' to 'unsigned short' may lose accuracy. */ - return ((u16_t)p[0]) << 8 | p[1]; + u16 = (u16_t)u8 << 8 | u8; } /* * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of * expressions of the form 'integer & constant', see can_represent. */ -static inline void -be32enc(void *buf, u32_t u) +void +be32enc(void) { - u8_t *p = buf; - - p[0] = u >> 24 & 0xff; - p[1] = u >> 16 & 0xff; - p[2] = u >> 8 & 0xff; - p[3] = u & 0xff; + u8 = u32 >> 24 & 0xff; + u8 = u32 >> 16 & 0xff; + u8 = u32 >> 8 & 0xff; + u8 = u32 & 0xff; } void test_ic_mult(void) { + /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ + u8 = u8 * u8; + u16 = u8 * u8; + /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ + u16 = u16 * u8; + u32 = u16 * u16; + u32 = u16 * 65537ULL; /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ u32 = u16 * 65538ULL; @@ -245,81 +248,25 @@ test_ic_mult(void) /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ u16 = 2 * u16; + // from __BITS, __SHIFTIN, __SHIFTOUT u32 = (u16 & 1023ULL) / 1ULL * 1024ULL | (u16 & 1023ULL) / 1ULL * 1ULL; } -u32_t -test_ic_shr(u64_t x) -{ - if (x > 3) - return x >> 32; - if (x > 2) - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ - return x >> 31; - - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ - u32 = u64 >> 31; - u32 = u64 >> 32; - u16 = u64 >> 48; - u8 = u64 >> 56; - u16 = u32 >> 16; - u8 = u32 >> 24; - u8 = u16 >> 8; - - /* - * No matter whether the big integer is signed or unsigned, the - * result of '&' is guaranteed to be an unsigned value. - */ - u8 = (s64 & 0xf0) >> 4; - u8 = (s8 & 0xf0) >> 4; - - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ - return x; -} - -unsigned char -test_bit_fields(unsigned long long m) -{ - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */ - bits.u3 = bits.u32 & m; - - bits.u5 = bits.u3 & m; - bits.u32 = bits.u5 & m; - - /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ - 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) -{ - return lhs << rhs; -} - -u64_t -u64_shr(u64_t lhs, u64_t rhs) -{ - return lhs >> rhs; -} - -s64_t -s64_shl(s64_t lhs, s64_t rhs) -{ - return lhs << rhs; -} - -s64_t -s64_shr(s64_t lhs, s64_t rhs) +void +test_ic_div(void) { - return lhs >> rhs; + // FIXME + /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ + u8 = u8 / u8; + // FIXME + /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ + u8 = u16 / u8; + // FIXME + /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ + u16 = u8 / u8; + u16 = u32 / 65536; + /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ + u16 = u32 / 65535; } void @@ -367,16 +314,60 @@ test_ic_mod(void) } void -test_ic_bitand(void) +test_ic_shl(void) +{ + u64 = u64 << u64; + s64 = s64 << s64; + + u16 = u8 << 8; + /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ + u16 = u8 << 9; + u32 = u16 << 16; + // XXX: missing warning as UINT has the same rank as INT, see portable_rank_cmp. + u32 = u16 << 17; + /* expect+1: warning: shift amount 56 is greater than bit-size 32 of 'int' [122] */ + u64 = u8 << 56; + u64 = (u64_t)u8 << 56; + // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. + u64 = (u64_t)u8 << 57; + /* expect+1: warning: shift amount 48 is greater than bit-size 32 of 'int' [122] */ + u64 = u16 << 48; + u64 = (u64_t)u16 << 48; + // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. + u64 = (u64_t)u16 << 49; + /* expect+1: warning: shift amount 32 equals bit-size of 'unsigned int' [267] */ + u64 = u32 << 32; + u64 = (u64_t)u32 << 32; + // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. + u64 = (u64_t)u32 << 33; +} + +void +test_ic_shr(void) { + u64 = u64 >> u64; + s64 = s64 >> s64; + + u32 = u64 >> 32; + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ + u32 = u64 >> 31; + u16 = u64 >> 48; + u16 = u32 >> 16; + u8 = u64 >> 56; + u8 = u32 >> 24; + u8 = u16 >> 8; + /* - * ic_bitand assumes that integers are represented in 2's complement, - * and that the sign bit of signed integers behaves like a value bit. - * That way, the following expressions get their constraints computed - * correctly, regardless of whether ic_expr takes care of integer - * promotions or not. Compare ic_mod, which ignores signed types. + * No matter whether the big integer is signed or unsigned, the + * result of '&' is guaranteed to be an unsigned value. */ + u8 = (s64 & 0xf0) >> 4; + u8 = (s8 & 0xf0) >> 4; +} +void +test_ic_bitand(void) +{ u8 = u8 & u16; /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ @@ -384,14 +375,21 @@ test_ic_bitand(void) } void -test_ic_cvt(void) +test_ic_bitor(void) { - u16 = (u32 & 0x0000ff00); - u16 = (u32_t)(u32 & 0x0000ff00); + /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ + u8 = u8 | u16; + u16 = u8 | u16; + /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ + u16 = u8 | u32; + u32 = u8 | u32; + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ + u32 = u8 | u64; + u64 = u8 | u64; } void -test_ic_conditional(char c1, char c2) +test_ic_quest_colon(char c1, char c2) { /* Both operands are representable as char. */ ch = cond ? '?' : ':'; @@ -404,21 +402,56 @@ test_ic_conditional(char c1, char c2) ch = cond ? c1 : c2; /* - * Mixing s8 and u8 results in a number from -128 to 255, which does - * not necessarily fit into s8. + * Mixing s8 and u8 results in a number from -128 to 255, which neither + * fits in s8 nor u8. */ /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ s8 = cond ? s8 : u8; - - /* - * Mixing s8 and u8 results in a number from -128 to 255, which does - * not necessarily fit into u8. - */ /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ u8 = cond ? s8 : u8; } void +test_ic_con(void) +{ + /* expect+1: warning: assignment of negative constant -1 to unsigned type 'unsigned char' [164] */ + u8 = -1; + u8 = 0; + u8 = 255; + /* expect+1: warning: constant truncated by assignment [165] */ + u8 = 256; + + /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */ + s8 = -129; + s8 = -128; + s8 = 127; + /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */ + s8 = 128; +} + +void +test_ic_cvt(void) +{ + u16 = (u32 & 0x0000ff00); + u16 = (u32_t)(u32 & 0x0000ff00); + u16 = (u16_t)u32; + u16 = (u8_t)(u32 & 0xffff) << 8; +} + +unsigned char +test_bit_fields(unsigned long long m) +{ + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */ + bits.u3 = bits.u32 & m; + + bits.u5 = bits.u3 & m; + bits.u32 = bits.u5 & m; + + /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ + return bits.u32 & m; +} + +void compare_bit_field_to_integer_constant(void) { static _Bool b;