xref: /netbsd-src/tests/usr.bin/xlint/lint1/queries.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /*	$NetBSD: queries.c,v 1.9 2023/01/15 14:00:09 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 */
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 /*
299  * Since queries do not affect the exit status, force a warning to make this
300  * test conform to the general expectation that a test that produces output
301  * exits non-successfully.
302  */
303 /* expect+1: warning: static variable 'unused' unused [226] */
304 static int unused;
305