1 /* $NetBSD: msg_309.c,v 1.9 2025/07/08 17:43:54 rillig Exp $ */ 2 # 3 "msg_309.c" 3 4 // Test for message: '%s' converts '%s' with its most significant bit being set to '%s' [309] 5 6 /* lint1-extra-flags: -X 351 */ 7 8 typedef unsigned char u8_t; 9 typedef unsigned short u16_t; 10 typedef unsigned int u32_t; 11 typedef unsigned long long u64_t; 12 13 u8_t u8; 14 u16_t u16; 15 u32_t u32; 16 u64_t u64; 17 18 19 void 20 test(void) 21 { 22 23 /* 24 * Both operands of '&' have the same type, therefore no conversion 25 * is necessary and no bits can get lost. 26 */ 27 u64 = u64 & 0xffffffff00000000ULL; 28 29 /* 30 * The constant has type 'unsigned 32-bit'. The usual arithmetic 31 * conversions of '&' convert this constant to unsigned 64-bit. 32 * The programmer may or may not have intended to sign-extend the 33 * bit mask here. This situation may occur during migration from a 34 * 32-bit to a 64-bit platform. 35 */ 36 /* expect+1: warning: '&' converts 'unsigned int' with its most significant bit being set to 'unsigned long long' [309] */ 37 u64 = u64 & 0xffff0000; 38 39 /* 40 * The integer constant is explicitly unsigned. Even in this case, 41 * the code may have originated on a platform where 'x' had 32 bits 42 * originally, and the intention may have been to clear the lower 16 43 * bits. 44 */ 45 /* expect+1: warning: '&' converts 'unsigned int' with its most significant bit being set to 'unsigned long long' [309] */ 46 u64 = u64 & 0xffff0000U; 47 48 /* 49 * Even if the expression is written as '& ~', which makes the 50 * intention of clearing the lower 16 bits clear, on a 32-bit 51 * platform the integer constant stays at 32 bits, and when porting 52 * the code to a 64-bit platform, the upper 32 bits are preserved. 53 */ 54 /* expect+1: warning: '&' converts 'unsigned int' with its most significant bit being set to 'unsigned long long' [309] */ 55 u64 = u64 & ~0xffffU; 56 57 /* 58 * Casting the integer constant to the proper type removes all 59 * ambiguities about the programmer's intention. 60 */ 61 u64 = u64 & (u64_t)~0xffffU; 62 63 /* 64 * In the remaining cases, the constant does not have its most 65 * significant bit set, therefore there is no ambiguity. 66 */ 67 u64 = u64 & 0xff00; 68 u64 = u64 & 0xf0; 69 u64 = u64 & 0xc; 70 u64 = u64 & 0x2; 71 u64 = u64 & 0x1; 72 73 u8 = u8 & 0x7f; 74 u8 = u8 & 0x80; 75 u8 = u8 & -0x80; 76 /* expect+1: warning: '&' converts 'unsigned char' with its most significant bit being set to 'int' [309] */ 77 u8 = u8 & (u8_t)-0x80; 78 /* expect+1: warning: '&' converts 'unsigned char' with its most significant bit being set to 'int' [309] */ 79 u8 = u8 & (u8_t)-0x80U; 80 81 /* expect+1: warning: '&=' converts 'unsigned short' with its most significant bit being set to 'int' [309] */ 82 u16 &= (u16_t)~0x0600; 83 /* expect+1: warning: '&' converts 'unsigned short' with its most significant bit being set to 'int' [309] */ 84 u16 = u16 & (u16_t)~0x0600; 85 /* expect+1: warning: '&' converts 'unsigned short' with its most significant bit being set to 'int' [309] */ 86 u16 = (u16_t)(u16 & (u16_t)~0x0600); 87 } 88