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