queries.c revision 1.13 1 /* $NetBSD: queries.c,v 1.13 2023/05/13 20:55:44 rillig Exp $ */
2 # 3 "queries.c"
3
4 /*
5 * Demonstrate the case-by-case queries. Unlike warnings, queries do not
6 * point to questionable code but rather to code that may be interesting to
7 * inspect manually on a case-by-case basis.
8 *
9 * Possible use cases are:
10 *
11 * Understanding how C works internally, by making the usual arithmetic
12 * conversions visible.
13 *
14 * Finding code that intentionally suppresses a regular lint warning,
15 * such as casts between arithmetic types.
16 */
17
18 /* lint1-extra-flags: -q 1,2,3,4,5,6,7,8,9,10 -X 351 */
19
20 typedef unsigned char u8_t;
21 typedef unsigned short u16_t;
22 typedef unsigned int u32_t;
23 typedef unsigned long long u64_t;
24 typedef signed char s8_t;
25 typedef signed short s16_t;
26 typedef signed int s32_t;
27 typedef signed long long s64_t;
28
29 typedef float f32_t;
30 typedef double f64_t;
31 typedef float _Complex c32_t;
32 typedef double _Complex c64_t;
33
34 typedef char *str_t;
35 typedef const char *cstr_t;
36 typedef volatile char *vstr_t;
37
38 _Bool cond;
39
40 u8_t u8;
41 u16_t u16;
42 u32_t u32;
43 u64_t u64;
44
45 s8_t s8;
46 s16_t s16;
47 s32_t s32;
48 s64_t s64;
49
50 struct {
51 unsigned u8:8;
52 unsigned u9:9;
53 unsigned u10:10;
54 unsigned u32:32;
55 int s8:8;
56 int s9:9;
57 int s10:10;
58 int s32:32;
59 } bits;
60
61 f32_t f32;
62 f64_t f64;
63
64 c32_t c32;
65 c64_t c64;
66
67 char *str;
68 const char *cstr;
69 volatile char *vstr;
70
71 int
72 Q1(double dbl)
73 {
74 /* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
75 return dbl;
76 }
77
78 int
79 Q2(double dbl)
80 {
81 /* expect+1: cast from floating point 'double' to integer 'int' [Q2] */
82 return (int)dbl;
83 }
84
85 void
86 Q3(int i, unsigned u)
87 {
88 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
89 u = i;
90
91 /* expect+1: implicit conversion changes sign from 'unsigned int' to 'int' [Q3] */
92 i = u;
93 }
94
95 unsigned long long
96 Q4(signed char *ptr, int i, unsigned long long ull)
97 {
98
99 /*
100 * For constants, the usual arithmetic conversions are usually not
101 * interesting, so omit them.
102 */
103 u32 = u32 & 0xff;
104 u32 &= 0xff;
105
106 /* expect+2: usual arithmetic conversion for '&' from 'int' to 'unsigned int' [Q4] */
107 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
108 u32 = u32 & s32;
109 /*
110 * XXX: C99 5.6.16.2 says that the usual arithmetic conversions
111 * happen for compound assignments as well.
112 */
113 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
114 u32 &= s32;
115
116 /* expect+3: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
117 /* expect+2: usual arithmetic conversion for '&' from 'int' to 'unsigned int' [Q4] */
118 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
119 u32 = u32 & u8;
120
121 /*
122 * The conversion from 'signed char' to 'int' is done by the integer
123 * promotions (C11 6.3.1.1p2), not by the usual arithmetic
124 * conversions (C11 6.3.1.8p1).
125 */
126 /* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */
127 /* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */
128 return ptr[0] + ptr[1] + i + ull;
129 }
130
131 void
132 Q5(signed char *ptr, int i)
133 {
134 if (ptr + i > ptr)
135 return;
136
137 /* expect+1: pointer addition has integer on the left-hand side [Q5] */
138 if (i + ptr > ptr)
139 return;
140
141 if (ptr[i] != '\0')
142 return;
143
144 /* expect+1: pointer addition has integer on the left-hand side [Q5] */
145 if (i[ptr] != '\0')
146 return;
147 }
148
149 void
150 Q6(int i)
151 {
152 /* expect+1: no-op cast from 'int' to 'int' [Q6] */
153 i = (int)4;
154
155 /* expect+1: no-op cast from 'int' to 'int' [Q6] */
156 i = (int)i + 1;
157 }
158
159 extern void *allocate(void);
160
161 void
162 Q7(void)
163 {
164
165 /* expect+2: no-op cast from '_Bool' to '_Bool' [Q6] */
166 /* expect+1: redundant cast from '_Bool' to '_Bool' before assignment [Q7] */
167 cond = (_Bool)cond;
168 cond = (_Bool)u8;
169 u8 = (u8_t)cond;
170
171 /* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
172 /* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */
173 u8 = (u8_t)u8;
174 u8 = (u8_t)u16;
175 u8 = (u16_t)u8;
176 /* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
177 u8 = (u16_t)u16;
178 /* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
179 u16 = (u8_t)u8;
180 u16 = (u8_t)u16;
181 /* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */
182 u16 = (u16_t)u8;
183 /* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
184 /* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */
185 u16 = (u16_t)u16;
186
187 /* Mixing signed and unsigned types. */
188 u8 = (u8_t)s8;
189 s8 = (s8_t)u8;
190 /* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */
191 s16 = (s16_t)u8;
192 /* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */
193 s16 = (s16_t)s8;
194
195
196 /*
197 * Neither GCC nor Clang accept typeof(bit-field), as that would add
198 * unnecessary complexity. Lint accepts it but silently discards the
199 * bit-field portion from the type; see dcs_add_type.
200 */
201 /* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */
202 bits.u9 = (typeof(bits.u9))u8;
203
204
205 /* expect+2: no-op cast from 'float' to 'float' [Q6] */
206 /* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */
207 f32 = (f32_t)f32;
208 f32 = (f32_t)f64;
209 f32 = (f64_t)f32;
210 /* expect+1: no-op cast from 'double' to 'double' [Q6] */
211 f32 = (f64_t)f64;
212 /* expect+1: no-op cast from 'float' to 'float' [Q6] */
213 f64 = (f32_t)f32;
214 f64 = (f32_t)f64;
215 /* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */
216 f64 = (f64_t)f32;
217 /* expect+2: no-op cast from 'double' to 'double' [Q6] */
218 /* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */
219 f64 = (f64_t)f64;
220
221
222 /* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
223 /* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */
224 c32 = (c32_t)c32;
225 c32 = (c32_t)c64;
226 c32 = (c64_t)c32;
227 /* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
228 c32 = (c64_t)c64;
229 /* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
230 c64 = (c32_t)c32;
231 c64 = (c32_t)c64;
232 /* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */
233 c64 = (c64_t)c32;
234 /* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
235 /* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */
236 c64 = (c64_t)c64;
237
238
239 /* Mixing real and complex floating point types. */
240 /* expect+1: no-op cast from 'float' to 'float' [Q6] */
241 c32 = (f32_t)f32;
242 c32 = (c32_t)f32;
243 /* expect+1: no-op cast from 'float' to 'float' [Q6] */
244 c64 = (f32_t)f32;
245 c64 = (f64_t)f32;
246 c64 = (c32_t)f32;
247 c64 = (c64_t)f32;
248
249
250 /*
251 * Converting a void pointer type to an object pointer type requires
252 * an explicit cast in C++, as it is a narrowing conversion. In C,
253 * that conversion is done implicitly.
254 */
255
256 /* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
257 str = (char *)allocate();
258 /* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */
259 cstr = (const char *)allocate();
260 cstr = (char *)allocate();
261
262 /* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
263 /* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
264 str = (str_t)str;
265 str = (str_t)cstr;
266 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
267 str = (cstr_t)str;
268 /* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
269 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
270 str = (cstr_t)cstr;
271 /* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
272 cstr = (str_t)str;
273 cstr = (str_t)cstr;
274 cstr = (cstr_t)str;
275 /* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
276 /* expect+1: redundant cast from 'pointer to const char' to 'pointer to const char' before assignment [Q7] */
277 cstr = (cstr_t)cstr;
278
279 /* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
280 /* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
281 str = (str_t)str;
282 str = (str_t)vstr;
283 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
284 str = (vstr_t)str;
285 /* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
286 /* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
287 str = (vstr_t)vstr;
288 /* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
289 vstr = (str_t)str;
290 vstr = (str_t)vstr;
291 vstr = (vstr_t)str;
292 /* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
293 /* expect+1: redundant cast from 'pointer to volatile char' to 'pointer to volatile char' before assignment [Q7] */
294 vstr = (vstr_t)vstr;
295 }
296
297 /*
298 * Octal numbers were common in the 1970s, especially on 36-bit machines.
299 * 50 years later, they are still used in numeric file permissions.
300 */
301 void
302 Q8(void)
303 {
304
305 u16 = 0;
306 u16 = 000000;
307 /* expect+1: octal number '0644' [Q8] */
308 u16 = 0644;
309 /* expect+1: octal number '0000644' [Q8] */
310 u16 = 0000644;
311 }
312
313 int
314 Q9(int x)
315 {
316 switch (x) {
317 case 0:
318 return 0;
319 case 1:
320 /* expect+1: parenthesized return value [Q9] */
321 return (0);
322 case 2:
323 return +(0);
324 case 3:
325 return -(13);
326 case 4:
327 /* expect+1: parenthesized return value [Q9] */
328 return (0), (1);
329 case 5:
330 /* expect+1: parenthesized return value [Q9] */
331 return (0, 1);
332 case 6:
333 return 0, 1;
334 case 7:
335 /* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
336 return 0.0;
337 case 8:
338 /* expect+2: parenthesized return value [Q9] */
339 /* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
340 return (0.0);
341 case 9:
342 return
343 # 344 "queries.c" 3 4
344 ((void *)0)
345 # 346 "queries.c"
346 /* expect+1: warning: illegal combination of integer 'int' and pointer 'pointer to void' [183] */
347 ;
348 case 10:
349 /* expect+1: warning: illegal combination of integer 'int' and pointer 'pointer to void' [183] */
350 return (void *)(0);
351 default:
352 return 0;
353 }
354 }
355
356 void
357 Q10(void)
358 {
359 int a, b, c;
360
361 /* expect+2: chained assignment with '=' and '=' [Q10] */
362 /* expect+1: chained assignment with '=' and '=' [Q10] */
363 a = b = c = 0;
364
365 /* expect+2: chained assignment with '*=' and '-=' [Q10] */
366 /* expect+1: chained assignment with '+=' and '*=' [Q10] */
367 a += b *= c -= 0;
368 }
369
370 /*
371 * Since queries do not affect the exit status, force a warning to make this
372 * test conform to the general expectation that a test that produces output
373 * exits non-successfully.
374 */
375 /* expect+1: warning: static variable 'unused' unused [226] */
376 static int unused;
377