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