queries.c revision 1.4 1 /* $NetBSD: queries.c,v 1.4 2022/08/28 08:41:06 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(char *ptr, int i, unsigned long long ull)
97 {
98 /*
99 * The conversion from '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(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