Home | History | Annotate | Line # | Download | only in lint1
      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