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