xref: /netbsd-src/tests/usr.bin/xlint/lint1/queries.c (revision 867d70fc718005c0918b8b8b2f9d7f2d52d0a0db)
1 /*	$NetBSD: queries.c,v 1.6 2022/09/24 19: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 */
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 	 * The conversion from 'signed char' to 'int' is done by the integer
100 	 * promotions (C11 6.3.1.1p2), not by the usual arithmetic
101 	 * conversions (C11 6.3.1.8p1).
102 	 */
103 	/* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */
104 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */
105 	return ptr[0] + ptr[1] + i + ull;
106 }
107 
108 void
109 Q5(signed char *ptr, int i)
110 {
111 	if (ptr + i > ptr)
112 		return;
113 
114 	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
115 	if (i + ptr > ptr)
116 		return;
117 
118 	if (ptr[i] != '\0')
119 		return;
120 
121 	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
122 	if (i[ptr] != '\0')
123 		return;
124 }
125 
126 void
127 Q6(int i)
128 {
129 	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
130 	i = (int)4;
131 
132 	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
133 	i = (int)i + 1;
134 }
135 
136 extern void *allocate(void);
137 
138 void
139 Q7(void)
140 {
141 
142 	/* expect+2: no-op cast from '_Bool' to '_Bool' [Q6] */
143 	/* expect+1: redundant cast from '_Bool' to '_Bool' before assignment [Q7] */
144 	cond = (_Bool)cond;
145 	cond = (_Bool)u8;
146 	u8 = (u8_t)cond;
147 
148 	/* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
149 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */
150 	u8 = (u8_t)u8;
151 	u8 = (u8_t)u16;
152 	u8 = (u16_t)u8;
153 	/* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
154 	u8 = (u16_t)u16;
155 	/* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
156 	u16 = (u8_t)u8;
157 	u16 = (u8_t)u16;
158 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */
159 	u16 = (u16_t)u8;
160 	/* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
161 	/* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */
162 	u16 = (u16_t)u16;
163 
164 	/* Mixing signed and unsigned types. */
165 	u8 = (u8_t)s8;
166 	s8 = (s8_t)u8;
167 	/* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */
168 	s16 = (s16_t)u8;
169 	/* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */
170 	s16 = (s16_t)s8;
171 
172 
173 	/*
174 	 * Neither GCC nor Clang accept typeof(bit-field), as that would add
175 	 * unnecessary complexity.  Lint accepts it but silently discards the
176 	 * bit-field portion from the type; see dcs_add_type.
177 	 */
178 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */
179 	bits.u9 = (typeof(bits.u9))u8;
180 
181 
182 	/* expect+2: no-op cast from 'float' to 'float' [Q6] */
183 	/* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */
184 	f32 = (f32_t)f32;
185 	f32 = (f32_t)f64;
186 	f32 = (f64_t)f32;
187 	/* expect+1: no-op cast from 'double' to 'double' [Q6] */
188 	f32 = (f64_t)f64;
189 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
190 	f64 = (f32_t)f32;
191 	f64 = (f32_t)f64;
192 	/* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */
193 	f64 = (f64_t)f32;
194 	/* expect+2: no-op cast from 'double' to 'double' [Q6] */
195 	/* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */
196 	f64 = (f64_t)f64;
197 
198 
199 	/* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
200 	/* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */
201 	c32 = (c32_t)c32;
202 	c32 = (c32_t)c64;
203 	c32 = (c64_t)c32;
204 	/* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
205 	c32 = (c64_t)c64;
206 	/* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
207 	c64 = (c32_t)c32;
208 	c64 = (c32_t)c64;
209 	/* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */
210 	c64 = (c64_t)c32;
211 	/* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
212 	/* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */
213 	c64 = (c64_t)c64;
214 
215 
216 	/* Mixing real and complex floating point types. */
217 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
218 	c32 = (f32_t)f32;
219 	c32 = (c32_t)f32;
220 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
221 	c64 = (f32_t)f32;
222 	c64 = (f64_t)f32;
223 	c64 = (c32_t)f32;
224 	c64 = (c64_t)f32;
225 
226 
227 	/* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
228 	str = (char *)allocate();
229 	/* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */
230 	cstr = (const char *)allocate();
231 	cstr = (char *)allocate();
232 
233 	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
234 	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
235 	str = (str_t)str;
236 	str = (str_t)cstr;
237 	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
238 	str = (cstr_t)str;
239 	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
240 	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'const char' [128] */
241 	str = (cstr_t)cstr;
242 	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
243 	cstr = (str_t)str;
244 	cstr = (str_t)cstr;
245 	cstr = (cstr_t)str;
246 	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
247 	/* expect+1: redundant cast from 'pointer to const char' to 'pointer to const char' before assignment [Q7] */
248 	cstr = (cstr_t)cstr;
249 
250 	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
251 	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
252 	str = (str_t)str;
253 	str = (str_t)vstr;
254 	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
255 	str = (vstr_t)str;
256 	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
257 	/* expect+1: warning: operands of '=' have incompatible pointer types to 'char' and 'volatile char' [128] */
258 	str = (vstr_t)vstr;
259 	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
260 	vstr = (str_t)str;
261 	vstr = (str_t)vstr;
262 	vstr = (vstr_t)str;
263 	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
264 	/* expect+1: redundant cast from 'pointer to volatile char' to 'pointer to volatile char' before assignment [Q7] */
265 	vstr = (vstr_t)vstr;
266 }
267 
268 
269 /*
270  * Since queries do not affect the exit status, force a warning to make this
271  * test conform to the general expectation that a test that produces output
272  * exits non-successfully.
273  */
274 /* expect+1: warning: static variable 'unused' unused [226] */
275 static int unused;
276