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