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