1 /* $NetBSD: msg_117.c,v 1.14 2023/07/07 19:45:22 rillig Exp $ */ 2 # 3 "msg_117.c" 3 4 // Test for message: bitwise '%s' on signed value possibly nonportable [117] 5 6 /* lint1-extra-flags: -p -X 351 */ 7 8 int 9 shr(int a, int b) 10 { 11 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 12 return a >> b; 13 } 14 15 int 16 shr_lhs_constant_positive(int a) 17 { 18 return 0x1234 >> a; 19 } 20 21 int 22 shr_lhs_constant_negative(int a) 23 { 24 /* expect+1: warning: bitwise '>>' on signed value nonportable [120] */ 25 return -0x1234 >> a; 26 } 27 28 int 29 shr_rhs_constant_positive(int a) 30 { 31 /* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */ 32 /* expect+1: warning: shift amount 4660 is greater than bit-size 32 of 'int' [122] */ 33 return a >> 0x1234; 34 } 35 36 int 37 shr_rhs_constant_negative(int a) 38 { 39 /* expect+2: warning: bitwise '>>' on signed value possibly nonportable [117] */ 40 /* expect+1: warning: negative shift [121] */ 41 return a >> -0x1234; 42 } 43 44 unsigned int 45 shr_unsigned_char(unsigned char uc) 46 { 47 /* 48 * Even though 'uc' is promoted to 'int', it cannot be negative. 49 * Before tree.c 1.335 from 2021-08-15, lint wrongly warned that 50 * 'uc >> 4' might be a bitwise '>>' on signed value. 51 */ 52 return uc >> 4; 53 } 54 55 unsigned char 56 shr_unsigned_char_promoted_signed(unsigned char bit) 57 { 58 /* 59 * The possible values for 'bit' range from 0 to 255. Subtracting 1 60 * from 0 results in a negative expression value. 61 */ 62 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 63 return (unsigned char)((bit - 1) >> 5); 64 } 65 66 unsigned char 67 shr_unsigned_char_promoted_unsigned(unsigned char bit) 68 { 69 /* 70 * To prevent the above warning, the intermediate expression must be 71 * cast to 'unsigned char'. 72 */ 73 return (unsigned char)((unsigned char)(bit - 1) >> 5); 74 } 75 76 /* 77 * C90 3.3.7, C99 6.5.7 and C11 6.5.7 all say the same: If E1 has a signed 78 * type and a negative value, the resulting value is implementation-defined. 79 * 80 * These standards don't guarantee anything about the lower bits of the 81 * resulting value, which are generally independent of whether the shift is 82 * performed in signed arithmetics or in unsigned arithmetics. The C99 83 * rationale talks about signed shifts, but does not provide any guarantee 84 * either. It merely suggests that platforms are free to use unsigned shifts 85 * even if the operand type is signed. 86 * 87 * K&R provides more guarantees by saying: Right shifting a signed quantity 88 * will fill with sign bits ("arithmetic shift") on some machines such as the 89 * PDP-11, and with 0-bits ("logical shift") on others. 90 * 91 * https://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html says: 92 * Signed '>>' acts on negative numbers by sign extension. 93 * 94 * This means that at least in GCC mode, lint may decide to not warn about 95 * these cases. 96 */ 97 void 98 shr_signed_ignoring_high_bits(int x) 99 { 100 101 /* 102 * All sane platforms should define that 'x >> 0 == x', even if x is 103 * negative. 104 */ 105 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 106 if (x >> 0 != 0) 107 return; 108 109 /* 110 * If x is negative, x >> 1 is nonzero, no matter whether the shift 111 * is arithmetic or logical. 112 */ 113 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 114 if (x >> 1 != 0) 115 return; 116 117 /* 118 * The highest bit may be 0 or 1, the others should be well-defined 119 * on all sane platforms, making it irrelevant whether the actual 120 * shift operation is arithmetic or logical. 121 */ 122 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 123 if (((x >> 1) & 1) != 0) 124 return; 125 126 /* 127 * The result of this expression is the same with arithmetic and 128 * logical shifts since the filled bits are masked out. 129 */ 130 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 131 if (((x >> 31) & 1) != 0) 132 return; 133 134 /* 135 * In this case, arithmetic shift results in 2 while logical shift 136 * results in 0. This difference is what this warning is about. 137 */ 138 /* expect+1: warning: bitwise '>>' on signed value possibly nonportable [117] */ 139 if (((x >> 31) & 2) != 0) 140 return; 141 142 /* 143 * The result of '&' is guaranteed to be positive, so don't warn. 144 * Code like this typically occurs in hexdump functions. 145 */ 146 if ((x & 0xf0) >> 4 != 0) 147 return; 148 } 149