Home | History | Annotate | Line # | Download | only in lint1
      1 /*	$NetBSD: msg_117.c,v 1.16 2025/09/14 14:42:52 rillig Exp $	*/
      2 # 3 "msg_117.c"
      3 
      4 // Test for message: bitwise '%s' on signed '%s' possibly nonportable [117]
      5 
      6 /* lint1-extra-flags: -p -X 351 */
      7 
      8 signed char s8;
      9 unsigned char u8;
     10 short s16;
     11 unsigned short u16;
     12 int s32;
     13 unsigned u32;
     14 long long s64;
     15 unsigned long long u64;
     16 
     17 // Shifting a signed integer left invokes undefined behavior if a 1 is shifted
     18 // to the sign bit or beyond. At runtime, KUBSAN performs this check.
     19 void
     20 shl(void)
     21 {
     22 	s32 = s8 << 0;
     23 	s32 = s8 << 23;
     24 	/* expect+1: warning: bitwise '<<' on signed 'int promoted from signed char' possibly nonportable [117] */
     25 	s32 = s8 << 24;
     26 	s32 = s8 << 31;
     27 	/* expect+1: warning: shift amount 32 equals bit-size of 'int promoted from signed char' [267] */
     28 	s32 = s8 << 32;
     29 	/* expect+1: warning: shift amount 32 equals bit-size of 'int promoted from signed char' [267] */
     30 	s64 = s8 << 32;
     31 
     32 	/*
     33 	 * When shifting 'uint8_t', it first gets promoted to 'int', which is
     34 	 * then subject to the overflow check. To prevent this, first cast the
     35 	 * 'uint8_t' to a suitable larger unsigned integer type.
     36 	 */
     37 	u32 = u8 << 0;
     38 	u32 = u8 << 23;
     39 	/* expect+1: warning: bitwise '<<' on signed 'int promoted from unsigned char' possibly nonportable [117] */
     40 	u32 = u8 << 24;
     41 	u32 = u8 << 31;
     42 	/* expect+1: warning: shift amount 32 equals bit-size of 'int promoted from unsigned char' [267] */
     43 	u32 = u8 << 32;
     44 	/* expect+1: warning: shift amount 32 equals bit-size of 'int promoted from unsigned char' [267] */
     45 	u64 = u8 << 32;
     46 
     47 	u32 = s32 << 0;
     48 	u32 = s32 << 23;
     49 	u32 = s32 << 24;
     50 	u32 = s32 << 31;
     51 	/* expect+1: warning: shift amount 32 equals bit-size of 'int' [267] */
     52 	u32 = s32 << 32;
     53 	/* expect+1: warning: shift amount 32 equals bit-size of 'int' [267] */
     54 	u64 = s32 << 32;
     55 
     56 	u32 = u32 << 0;
     57 	u32 = u32 << 23;
     58 	u32 = u32 << 24;
     59 	u32 = u32 << 31;
     60 	/* expect+1: warning: shift amount 32 equals bit-size of 'unsigned int' [267] */
     61 	u32 = u32 << 32;
     62 	/* expect+1: warning: shift amount 32 equals bit-size of 'unsigned int' [267] */
     63 	u64 = u32 << 32;
     64 }
     65 
     66 int
     67 shr(int a, int b)
     68 {
     69 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
     70 	return a >> b;
     71 }
     72 
     73 int
     74 shr_lhs_constant_positive(int a)
     75 {
     76 	return 0x1234 >> a;
     77 }
     78 
     79 int
     80 shr_lhs_constant_negative(int a)
     81 {
     82 	/* expect+1: warning: bitwise '>>' on signed 'int' nonportable [120] */
     83 	return -0x1234 >> a;
     84 }
     85 
     86 int
     87 shr_rhs_constant_positive(int a)
     88 {
     89 	/* expect+2: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
     90 	/* expect+1: warning: shift amount 4660 is greater than bit-size 32 of 'int' [122] */
     91 	return a >> 0x1234;
     92 }
     93 
     94 int
     95 shr_rhs_constant_negative(int a)
     96 {
     97 	/* expect+2: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
     98 	/* expect+1: warning: negative shift [121] */
     99 	return a >> -0x1234;
    100 }
    101 
    102 unsigned int
    103 shr_unsigned_char(unsigned char uc)
    104 {
    105 	/*
    106 	 * Even though 'uc' is promoted to 'int', it cannot be negative.
    107 	 * Before tree.c 1.335 from 2021-08-15, lint wrongly warned that
    108 	 * 'uc >> 4' might be a bitwise '>>' on signed value.
    109 	 */
    110 	return uc >> 4;
    111 }
    112 
    113 unsigned char
    114 shr_unsigned_char_promoted_signed(unsigned char bit)
    115 {
    116 	/*
    117 	 * The possible values for 'bit' range from 0 to 255.  Subtracting 1
    118 	 * from 0 results in a negative expression value.
    119 	 */
    120 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    121 	return (unsigned char)((bit - 1) >> 5);
    122 }
    123 
    124 unsigned char
    125 shr_unsigned_char_promoted_unsigned(unsigned char bit)
    126 {
    127 	/*
    128 	 * To prevent the above warning, the intermediate expression must be
    129 	 * cast to 'unsigned char'.
    130 	 */
    131 	return (unsigned char)((unsigned char)(bit - 1) >> 5);
    132 }
    133 
    134 /*
    135  * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed
    136  * type and a negative value, the resulting value is implementation-defined.
    137  *
    138  * These standards don't guarantee anything about the lower bits of the
    139  * resulting value, which are generally independent of whether the shift is
    140  * performed in signed arithmetics or in unsigned arithmetics.  The C99
    141  * rationale talks about signed shifts, but does not provide any guarantee
    142  * either.  It merely suggests that platforms are free to use unsigned shifts
    143  * even if the operand type is signed.
    144  *
    145  * K&R provides more guarantees by saying: Right shifting a signed quantity
    146  * will fill with sign bits ("arithmetic shift") on some machines such as the
    147  * PDP-11, and with 0-bits ("logical shift") on others.
    148  *
    149  * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says:
    150  * Signed '>>' acts on negative numbers by sign extension.
    151  *
    152  * This means that at least in GCC mode, lint may decide to not warn about
    153  * these cases.
    154  */
    155 void
    156 shr_signed_ignoring_high_bits(int x)
    157 {
    158 
    159 	/*
    160 	 * All sane platforms should define that 'x >> 0 == x', even if x is
    161 	 * negative.
    162 	 */
    163 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    164 	if (x >> 0 != 0)
    165 		return;
    166 
    167 	/*
    168 	 * If x is negative, x >> 1 is nonzero, no matter whether the shift
    169 	 * is arithmetic or logical.
    170 	 */
    171 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    172 	if (x >> 1 != 0)
    173 		return;
    174 
    175 	/*
    176 	 * The highest bit may be 0 or 1, the others should be well-defined
    177 	 * on all sane platforms, making it irrelevant whether the actual
    178 	 * shift operation is arithmetic or logical.
    179 	 */
    180 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    181 	if (((x >> 1) & 1) != 0)
    182 		return;
    183 
    184 	/*
    185 	 * The result of this expression is the same with arithmetic and
    186 	 * logical shifts since the filled bits are masked out.
    187 	 */
    188 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    189 	if (((x >> 31) & 1) != 0)
    190 		return;
    191 
    192 	/*
    193 	 * In this case, arithmetic shift results in 2 while logical shift
    194 	 * results in 0.  This difference is what this warning is about.
    195 	 */
    196 	/* expect+1: warning: bitwise '>>' on signed 'int' possibly nonportable [117] */
    197 	if (((x >> 31) & 2) != 0)
    198 		return;
    199 
    200 	/*
    201 	 * The result of '&' is guaranteed to be positive, so don't warn.
    202 	 * Code like this typically occurs in hexdump functions.
    203 	 */
    204 	if ((x & 0xf0) >> 4 != 0)
    205 		return;
    206 }
    207