d_c99_bool_strict.c revision 1.37 1 1.37 rillig /* $NetBSD: d_c99_bool_strict.c,v 1.37 2022/02/27 08:31:26 rillig Exp $ */
2 1.1 rillig # 3 "d_c99_bool_strict.c"
3 1.1 rillig
4 1.1 rillig /*
5 1.4 rillig * The option -T treats _Bool as incompatible with all other scalar types.
6 1.8 rillig * This is implemented by the following rules:
7 1.1 rillig *
8 1.8 rillig * strict-bool-typedef:
9 1.8 rillig * The type _Bool is compatible with any typedef of _Bool.
10 1.1 rillig *
11 1.8 rillig * Note: Since <stdbool.h> defines bool as textual alias of _Bool,
12 1.8 rillig * having another typedef for bool is unusual.
13 1.1 rillig *
14 1.8 rillig * strict-bool-constant:
15 1.8 rillig * There are 2 bool constants named false and true.
16 1.8 rillig * No other constants are compatible with type _Bool.
17 1.1 rillig *
18 1.8 rillig * Note: Internally these constants are named __lint_false and
19 1.8 rillig * __lint_true.
20 1.1 rillig *
21 1.8 rillig * strict-bool-bit-field:
22 1.8 rillig * A struct or union member that is a bit field with underlying type
23 1.8 rillig * bool is compatible with plain bool.
24 1.1 rillig *
25 1.8 rillig * strict-bool-conversion:
26 1.8 rillig * There is no implicit conversion between _Bool and any other type.
27 1.3 rillig *
28 1.8 rillig * strict-bool-controlling-expression:
29 1.8 rillig * Controlling expressions in 'if', 'while', 'for', '?:' must be of
30 1.8 rillig * type bool.
31 1.3 rillig *
32 1.8 rillig * strict-bool-operand-unary:
33 1.8 rillig * Operator bool? scalar?
34 1.25 rillig * ! yes -
35 1.25 rillig * & yes yes
36 1.25 rillig * The other unary operators do not accept bool operands.
37 1.8 rillig *
38 1.8 rillig * strict-bool-operand-binary:
39 1.8 rillig * Operator left: bool? other? right: bool? other?
40 1.8 rillig * . - yes yes yes
41 1.8 rillig * -> - yes yes yes
42 1.11 rillig * <=, <, >=, > - yes - yes
43 1.8 rillig * ==, != yes yes yes yes
44 1.8 rillig * & yes yes yes yes
45 1.8 rillig * ^ yes yes yes yes
46 1.8 rillig * | yes yes yes yes
47 1.8 rillig * && yes - yes -
48 1.8 rillig * || yes - yes -
49 1.8 rillig * ? yes - yes yes
50 1.8 rillig * : yes yes yes yes
51 1.8 rillig * = yes yes yes yes
52 1.8 rillig * &=, ^=, |= yes yes yes yes
53 1.8 rillig * , yes yes yes yes
54 1.8 rillig * The other binary operators do not accept bool operands.
55 1.8 rillig *
56 1.8 rillig * strict-bool-operator-result:
57 1.8 rillig * The result type of the operators '!', '<', '<=', '>', '>=',
58 1.8 rillig * '==', '!=', '&&', '||' is _Bool instead of int.
59 1.8 rillig *
60 1.8 rillig * strict-bool-bitwise-and:
61 1.8 rillig * Expressions of the form "flags & FLAG" are compatible with _Bool if
62 1.8 rillig * the left operand has enum type, the right operand is an integer
63 1.8 rillig * constant and the resulting value is used in a context where it is
64 1.8 rillig * implicitly and immediately compared to zero.
65 1.8 rillig *
66 1.8 rillig * Note: An efficient implementation technique for a collection of bool
67 1.8 rillig * flags is an enum. The enum declaration groups the available
68 1.8 rillig * constants, and as of 2020, compilers such as GCC and Clang have basic
69 1.8 rillig * support for detecting type mismatches on enums.
70 1.8 rillig *
71 1.8 rillig * Note: Examples for such contexts are controlling expressions or the
72 1.8 rillig * operands of the operators '!', '&&', '||'.
73 1.8 rillig *
74 1.8 rillig * Note: Counterexamples for contexts are assignments to a bool variable.
75 1.8 rillig *
76 1.8 rillig * Note: These rules ensure that conforming code can be compiled without
77 1.8 rillig * change in behavior using old compilers that implement bool as an
78 1.8 rillig * ordinary integer type, without the special rule C99 6.3.1.2.
79 1.8 rillig *
80 1.8 rillig * Note: There is a crucial difference between a _Bool variable and an
81 1.8 rillig * ordinary integer variable. C99 6.3.1.2 defines a conversion from an
82 1.8 rillig * arbitrary scalar value to _Bool as equivalent to (value != 0 ? 1 : 0).
83 1.8 rillig * This means that even if _Bool is implemented as an 8-bit unsigned
84 1.8 rillig * integer, assigning 256 to it would still result in the value 1 being
85 1.8 rillig * stored. Storing 256 in an ordinary 8-bit unsigned integer would
86 1.8 rillig * result in the value 0 being stored. See the test d_c99_bool.c for
87 1.8 rillig * more details.
88 1.8 rillig */
89 1.8 rillig
90 1.8 rillig /*
91 1.8 rillig * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and
92 1.8 rillig * true = 1. Without further hacks, this would mean that constant expressions
93 1.8 rillig * of integer type have to be regarded as possible boolean constants if their
94 1.8 rillig * value is either 0 or 1.
95 1.8 rillig *
96 1.8 rillig * This would not help in migrating old code to use bool consistently.
97 1.8 rillig * Therefore lint provides its own <stdbool.h> header that expands false to
98 1.8 rillig * __lint_false and true to __lint_true, two predefined constant expressions.
99 1.1 rillig */
100 1.1 rillig
101 1.19 rillig /* lint1-extra-flags: -hT */
102 1.1 rillig
103 1.1 rillig /*
104 1.8 rillig * strict-bool-typedef
105 1.1 rillig */
106 1.1 rillig
107 1.1 rillig /*
108 1.1 rillig * Using a typedef for bool does not hurt the checks, they all use the
109 1.1 rillig * underlying basic type (see tspec_t), which is BOOL.
110 1.1 rillig */
111 1.1 rillig typedef _Bool bool;
112 1.1 rillig
113 1.8 rillig extern void accept_bool(bool);
114 1.8 rillig extern void println(const char *);
115 1.8 rillig extern void take_arguments(bool, int, const char *, ...);
116 1.8 rillig extern void do_nothing(void);
117 1.8 rillig
118 1.8 rillig /*
119 1.8 rillig * strict-bool-constant
120 1.8 rillig */
121 1.8 rillig
122 1.8 rillig void
123 1.8 rillig strict_bool_constant(void)
124 1.8 rillig {
125 1.8 rillig accept_bool(__lint_false);
126 1.8 rillig accept_bool(__lint_true);
127 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
128 1.36 rillig accept_bool(0);
129 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
130 1.36 rillig accept_bool(1);
131 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
132 1.36 rillig accept_bool(2);
133 1.8 rillig }
134 1.8 rillig
135 1.8 rillig enum strict_bool_constant_expressions {
136 1.8 rillig /* Ok: __lint_false is a boolean constant expression. */
137 1.36 rillig /* expect+1: warning: constant in conditional context [161] */
138 1.36 rillig FALSE = __lint_false ? 100 : 101,
139 1.8 rillig
140 1.8 rillig /* Ok: __lint_true is a boolean constant expression. */
141 1.36 rillig /* expect+1: warning: constant in conditional context [161] */
142 1.36 rillig TRUE = __lint_true ? 100 : 101,
143 1.8 rillig
144 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
145 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
146 1.36 rillig INT0 = 0 ? 100 : 101,
147 1.8 rillig
148 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
149 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
150 1.36 rillig INT1 = 1 ? 100 : 101,
151 1.8 rillig
152 1.8 rillig /* Not ok: 2 is not a boolean constant. */
153 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
154 1.36 rillig INT2 = 2 ? 100 : 101,
155 1.8 rillig
156 1.8 rillig /* Not ok: compound integer expressions are not bool. */
157 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
158 1.36 rillig ARITH = (2 - 2) ? 100 : 101,
159 1.8 rillig
160 1.8 rillig /*
161 1.8 rillig * Without strict bool mode, these two variants of an expression can
162 1.8 rillig * occur when a preprocessor macro is either defined to 1 or left
163 1.27 rillig * empty (since C99), as in lint1/ops.def.
164 1.8 rillig *
165 1.27 rillig * In strict bool mode, the resulting expression can be compared
166 1.27 rillig * against 0 to achieve the same effect (so +0 != 0 or 1 + 0 != 0).
167 1.8 rillig */
168 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
169 1.36 rillig BINARY_PLUS = (1 + 0) ? 100 : 101,
170 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
171 1.36 rillig UNARY_PLUS = (+0) ? 100 : 101,
172 1.8 rillig
173 1.8 rillig /* The main operator '>' has return type bool. */
174 1.36 rillig /* expect+1: warning: constant in conditional context [161] */
175 1.36 rillig Q1 = (13 > 12) ? 100 : 101,
176 1.8 rillig
177 1.8 rillig /*
178 1.8 rillig * The parenthesized expression has type int and thus cannot be
179 1.8 rillig * used as the controlling expression in the '?:' operator.
180 1.8 rillig */
181 1.36 rillig /* expect+2: warning: constant in conditional context [161] */
182 1.36 rillig /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */
183 1.36 rillig Q2 = (13 > 12 ? 1 : 7) ? 100 : 101,
184 1.8 rillig
185 1.36 rillig /* expect+1: error: integral constant expression expected [55] */
186 1.36 rillig BINAND_BOOL = __lint_false & __lint_true,
187 1.8 rillig BINAND_INT = 0 & 1,
188 1.8 rillig
189 1.36 rillig /* expect+1: error: integral constant expression expected [55] */
190 1.36 rillig BINXOR_BOOL = __lint_false ^ __lint_true,
191 1.8 rillig BINXOR_INT = 0 ^ 1,
192 1.8 rillig
193 1.36 rillig /* expect+1: error: integral constant expression expected [55] */
194 1.36 rillig BINOR_BOOL = __lint_false | __lint_true,
195 1.8 rillig BINOR_INT = 0 | 1,
196 1.8 rillig
197 1.36 rillig /* expect+2: warning: constant in conditional context [161] */
198 1.36 rillig /* expect+1: error: integral constant expression expected [55] */
199 1.36 rillig LOGOR_BOOL = __lint_false || __lint_true,
200 1.36 rillig /* expect+2: error: left operand of '||' must be bool, not 'int' [331] */
201 1.36 rillig /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */
202 1.36 rillig LOGOR_INT = 0 || 1,
203 1.36 rillig
204 1.36 rillig /* expect+2: warning: constant in conditional context [161] */
205 1.36 rillig /* expect+1: error: integral constant expression expected [55] */
206 1.36 rillig LOGAND_BOOL = __lint_false && __lint_true,
207 1.36 rillig /* expect+2: error: left operand of '&&' must be bool, not 'int' [331] */
208 1.36 rillig /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */
209 1.36 rillig LOGAND_INT = 0 && 1,
210 1.8 rillig };
211 1.8 rillig
212 1.8 rillig /*
213 1.8 rillig * strict-bool-bit-fields
214 1.8 rillig */
215 1.8 rillig
216 1.8 rillig void
217 1.8 rillig strict_bool_bit_fields(void)
218 1.8 rillig {
219 1.8 rillig struct flags {
220 1.8 rillig bool bool_flag: 1;
221 1.8 rillig unsigned uint_flag: 1;
222 1.8 rillig };
223 1.8 rillig
224 1.8 rillig struct flags flags = { __lint_false, 0 };
225 1.8 rillig struct flags *flags_ptr = &flags;
226 1.8 rillig bool b;
227 1.8 rillig
228 1.8 rillig b = flags.bool_flag;
229 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != unsigned int) [107] */
230 1.36 rillig b = flags.uint_flag;
231 1.8 rillig flags.bool_flag = b;
232 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (unsigned int != _Bool) [107] */
233 1.36 rillig flags.uint_flag = b;
234 1.8 rillig
235 1.8 rillig b = flags_ptr->bool_flag;
236 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != unsigned int) [107] */
237 1.36 rillig b = flags_ptr->uint_flag;
238 1.8 rillig flags_ptr->bool_flag = b;
239 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (unsigned int != _Bool) [107] */
240 1.36 rillig flags_ptr->uint_flag = b;
241 1.8 rillig }
242 1.8 rillig
243 1.8 rillig void
244 1.8 rillig strict_bool_bit_fields_operand_conversion(void)
245 1.8 rillig {
246 1.8 rillig struct s {
247 1.8 rillig bool ordinary;
248 1.8 rillig bool bit_field: 1;
249 1.8 rillig };
250 1.8 rillig
251 1.24 rillig struct s s = { 0 > 0 };
252 1.8 rillig
253 1.8 rillig s.ordinary = s.ordinary | s.ordinary;
254 1.15 rillig s.bit_field = s.bit_field | s.bit_field;
255 1.8 rillig }
256 1.8 rillig
257 1.8 rillig /*
258 1.8 rillig * strict-bool-conversion
259 1.8 rillig */
260 1.8 rillig
261 1.8 rillig bool
262 1.8 rillig strict_bool_conversion_return_false(void)
263 1.8 rillig {
264 1.8 rillig return __lint_false;
265 1.8 rillig }
266 1.8 rillig
267 1.8 rillig bool
268 1.8 rillig strict_bool_conversion_return_true(void)
269 1.8 rillig {
270 1.8 rillig return __lint_true;
271 1.8 rillig }
272 1.8 rillig
273 1.8 rillig bool
274 1.8 rillig strict_bool_conversion_return_bool(bool b)
275 1.8 rillig {
276 1.8 rillig return b;
277 1.8 rillig }
278 1.8 rillig
279 1.8 rillig bool
280 1.8 rillig strict_bool_conversion_return_0(void)
281 1.8 rillig {
282 1.36 rillig /* expect+1: error: return value type mismatch (_Bool) and (int) [211] */
283 1.36 rillig return 0;
284 1.8 rillig }
285 1.8 rillig
286 1.8 rillig bool
287 1.8 rillig strict_bool_conversion_return_1(void)
288 1.8 rillig {
289 1.36 rillig /* expect+1: error: return value type mismatch (_Bool) and (int) [211] */
290 1.36 rillig return 1;
291 1.8 rillig }
292 1.8 rillig
293 1.8 rillig bool
294 1.8 rillig strict_bool_conversion_return_2(void)
295 1.8 rillig {
296 1.36 rillig /* expect+1: error: return value type mismatch (_Bool) and (int) [211] */
297 1.36 rillig return 2;
298 1.8 rillig }
299 1.8 rillig
300 1.36 rillig /* expect+2: warning: argument 'p' unused in function 'strict_bool_conversion_return_pointer' [231] */
301 1.8 rillig bool
302 1.36 rillig strict_bool_conversion_return_pointer(const void *p)
303 1.8 rillig {
304 1.36 rillig /* expect+1: error: return value type mismatch (_Bool) and (pointer) [211] */
305 1.36 rillig return p;
306 1.8 rillig }
307 1.8 rillig
308 1.8 rillig char
309 1.8 rillig strict_bool_conversion_return_false_as_char(void)
310 1.8 rillig {
311 1.36 rillig /* expect+1: error: return value type mismatch (char) and (_Bool) [211] */
312 1.36 rillig return __lint_false;
313 1.8 rillig }
314 1.8 rillig
315 1.8 rillig char
316 1.8 rillig strict_bool_conversion_return_true_as_char(void)
317 1.8 rillig {
318 1.36 rillig /* expect+1: error: return value type mismatch (char) and (_Bool) [211] */
319 1.36 rillig return __lint_true;
320 1.8 rillig }
321 1.8 rillig
322 1.8 rillig
323 1.1 rillig void
324 1.8 rillig strict_bool_conversion_function_argument(void)
325 1.1 rillig {
326 1.8 rillig accept_bool(__lint_false);
327 1.8 rillig accept_bool(__lint_true);
328 1.8 rillig }
329 1.8 rillig
330 1.8 rillig void
331 1.8 rillig strict_bool_conversion_function_argument_pass(bool b, int i, const char *p)
332 1.8 rillig {
333 1.8 rillig /* No conversion necessary. */
334 1.8 rillig take_arguments(b, i, p);
335 1.8 rillig
336 1.8 rillig /* Implicitly converting bool to other scalar types. */
337 1.36 rillig /* expect+2: error: argument #2 expects 'int', gets passed '_Bool' [334] */
338 1.36 rillig /* expect+1: error: argument #3 expects 'pointer', gets passed '_Bool' [334] */
339 1.36 rillig take_arguments(b, b, b);
340 1.8 rillig
341 1.8 rillig /* Implicitly converting int to bool (arg #1). */
342 1.36 rillig /* expect+2: error: argument #1 expects '_Bool', gets passed 'int' [334] */
343 1.36 rillig /* expect+1: warning: illegal combination of pointer (pointer to const char) and integer (int), arg #3 [154] */
344 1.36 rillig take_arguments(i, i, i);
345 1.8 rillig
346 1.8 rillig /* Implicitly converting pointer to bool (arg #1). */
347 1.36 rillig /* expect+2: error: argument #1 expects '_Bool', gets passed 'pointer' [334] */
348 1.36 rillig /* expect+1: warning: illegal combination of integer (int) and pointer (pointer to const char), arg #2 [154] */
349 1.36 rillig take_arguments(p, p, p);
350 1.8 rillig
351 1.8 rillig /* Passing bool as vararg. */
352 1.36 rillig /* TODO: maybe expect+1: arg#4 should not be bool but scalar */
353 1.36 rillig take_arguments(b, i, p, b, i, p);
354 1.8 rillig
355 1.8 rillig /* Passing a bool constant. */
356 1.8 rillig take_arguments(__lint_false, i, p);
357 1.8 rillig
358 1.8 rillig /* Passing a bool constant. */
359 1.8 rillig take_arguments(__lint_true, i, p);
360 1.8 rillig
361 1.8 rillig /* Trying to pass integer constants. */
362 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
363 1.36 rillig take_arguments(0, i, p);
364 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
365 1.36 rillig take_arguments(1, i, p);
366 1.36 rillig /* expect+1: error: argument #1 expects '_Bool', gets passed 'int' [334] */
367 1.36 rillig take_arguments(2, i, p);
368 1.8 rillig }
369 1.1 rillig
370 1.8 rillig void
371 1.8 rillig strict_bool_conversion_between_bool_and_int(void)
372 1.8 rillig {
373 1.8 rillig bool b;
374 1.8 rillig int i;
375 1.1 rillig
376 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
377 1.36 rillig b = 0;
378 1.9 rillig b = __lint_false;
379 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
380 1.36 rillig b = 1;
381 1.8 rillig b = __lint_true;
382 1.1 rillig
383 1.8 rillig i = 0;
384 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
385 1.36 rillig i = __lint_false;
386 1.8 rillig i = 1;
387 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
388 1.36 rillig i = __lint_true;
389 1.8 rillig
390 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
391 1.36 rillig i = b;
392 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
393 1.36 rillig b = i;
394 1.8 rillig }
395 1.8 rillig
396 1.36 rillig /* expect+2: warning: argument 'b' unused in function 'strict_bool_conversion_from_bool_to_scalar' [231] */
397 1.8 rillig void
398 1.36 rillig strict_bool_conversion_from_bool_to_scalar(bool b)
399 1.8 rillig {
400 1.8 rillig int i;
401 1.8 rillig unsigned u;
402 1.8 rillig double d;
403 1.8 rillig void *p;
404 1.8 rillig
405 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
406 1.36 rillig i = b;
407 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (unsigned int != _Bool) [107] */
408 1.36 rillig u = b;
409 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (double != _Bool) [107] */
410 1.36 rillig d = b;
411 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (pointer != _Bool) [107] */
412 1.36 rillig p = b;
413 1.8 rillig }
414 1.8 rillig
415 1.8 rillig /*
416 1.8 rillig * strict-bool-controlling-expression:
417 1.8 rillig * Controlling expressions in 'if', 'while', 'for', '?:' must be of
418 1.8 rillig * type bool.
419 1.8 rillig */
420 1.8 rillig
421 1.8 rillig void
422 1.8 rillig strict_bool_controlling_expression(bool b, int i, double d, const void *p)
423 1.8 rillig {
424 1.36 rillig /* expect+1: warning: constant in conditional context [161] */
425 1.36 rillig if (__lint_false)
426 1.36 rillig do_nothing();
427 1.36 rillig /* expect-1: warning: statement not reached [193] */
428 1.8 rillig
429 1.36 rillig /* expect+1: warning: constant in conditional context [161] */
430 1.36 rillig if (__lint_true)
431 1.8 rillig do_nothing();
432 1.8 rillig
433 1.8 rillig if (b)
434 1.8 rillig do_nothing();
435 1.8 rillig
436 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
437 1.36 rillig if (/*CONSTCOND*/0)
438 1.36 rillig do_nothing();
439 1.36 rillig /* expect-1: warning: statement not reached [193] */
440 1.8 rillig
441 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
442 1.36 rillig if (/*CONSTCOND*/1)
443 1.8 rillig do_nothing();
444 1.8 rillig
445 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
446 1.36 rillig if (/*CONSTCOND*/2)
447 1.8 rillig do_nothing();
448 1.1 rillig
449 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
450 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
451 1.36 rillig if (i)
452 1.8 rillig do_nothing();
453 1.1 rillig if (i != 0)
454 1.8 rillig do_nothing();
455 1.1 rillig
456 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
457 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'double' [333] */
458 1.36 rillig if (d)
459 1.8 rillig do_nothing();
460 1.1 rillig if (d != 0.0)
461 1.8 rillig do_nothing();
462 1.1 rillig
463 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
464 1.36 rillig /* expect+1: error: controlling expression must be bool, not 'pointer' [333] */
465 1.36 rillig if (p)
466 1.8 rillig do_nothing();
467 1.1 rillig if (p != (void *)0)
468 1.8 rillig do_nothing();
469 1.8 rillig }
470 1.1 rillig
471 1.8 rillig /*
472 1.8 rillig * strict-bool-operand-unary:
473 1.8 rillig * Operator bool? scalar?
474 1.8 rillig * ! yes -
475 1.8 rillig * & yes yes
476 1.25 rillig * The other unary operators do not accept bool operands.
477 1.8 rillig */
478 1.8 rillig
479 1.8 rillig void
480 1.8 rillig strict_bool_operand_unary_not(void)
481 1.8 rillig {
482 1.8 rillig bool b = __lint_false;
483 1.8 rillig
484 1.8 rillig b = !b;
485 1.8 rillig b = !!!b;
486 1.36 rillig /* expect+2: warning: constant in conditional context [161] */
487 1.36 rillig /* expect+1: warning: constant argument to '!' [239] */
488 1.36 rillig b = !__lint_false;
489 1.36 rillig /* expect+2: warning: constant in conditional context [161] */
490 1.36 rillig /* expect+1: warning: constant argument to '!' [239] */
491 1.36 rillig b = !__lint_true;
492 1.8 rillig
493 1.8 rillig int i = 0;
494 1.8 rillig
495 1.36 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
496 1.36 rillig i = !i;
497 1.36 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
498 1.36 rillig i = !!!i;
499 1.36 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
500 1.36 rillig i = !0;
501 1.36 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
502 1.36 rillig i = !1;
503 1.8 rillig }
504 1.8 rillig
505 1.8 rillig void
506 1.8 rillig strict_bool_operand_unary_address(void)
507 1.8 rillig {
508 1.8 rillig bool b = __lint_false;
509 1.8 rillig
510 1.8 rillig /* Taking the address of a bool lvalue. */
511 1.8 rillig bool *bp;
512 1.8 rillig bp = &b;
513 1.8 rillig *bp = b;
514 1.8 rillig b = *bp;
515 1.1 rillig }
516 1.1 rillig
517 1.29 rillig /* see strict_bool_operand_unary_all below for the other unary operators. */
518 1.29 rillig
519 1.8 rillig /*
520 1.8 rillig * strict-bool-operand-binary:
521 1.8 rillig * Operator left: bool? other? right: bool? other?
522 1.8 rillig * . - yes yes yes
523 1.8 rillig * -> - yes yes yes
524 1.11 rillig * <=, <, >=, > - yes - yes
525 1.8 rillig * ==, != yes yes yes yes
526 1.8 rillig * & yes yes yes yes
527 1.8 rillig * ^ yes yes yes yes
528 1.8 rillig * | yes yes yes yes
529 1.8 rillig * && yes - yes -
530 1.8 rillig * || yes - yes -
531 1.8 rillig * ? yes - yes yes
532 1.8 rillig * : yes yes yes yes
533 1.8 rillig * = yes yes yes yes
534 1.8 rillig * &=, ^=, |= yes yes yes yes
535 1.8 rillig * , yes yes yes yes
536 1.8 rillig * The other binary operators do not accept bool operands.
537 1.8 rillig */
538 1.8 rillig
539 1.8 rillig /*
540 1.8 rillig * Ensure that bool members can be accessed as usual.
541 1.8 rillig */
542 1.1 rillig void
543 1.8 rillig strict_bool_operand_binary_dot_arrow(void)
544 1.1 rillig {
545 1.8 rillig struct bool_struct {
546 1.8 rillig bool b;
547 1.8 rillig };
548 1.8 rillig
549 1.8 rillig /* Initialize and assign using boolean constants. */
550 1.8 rillig bool b = __lint_false;
551 1.8 rillig b = __lint_true;
552 1.1 rillig
553 1.8 rillig /* Access a struct member using the '.' operator. */
554 1.8 rillig struct bool_struct bs = { __lint_true };
555 1.8 rillig b = bs.b;
556 1.8 rillig bs.b = b;
557 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
558 1.36 rillig bs.b = 0;
559 1.1 rillig
560 1.8 rillig /* Access a struct member using the '->' operator. */
561 1.8 rillig struct bool_struct *bsp = &bs;
562 1.8 rillig b = bsp->b;
563 1.8 rillig bsp->b = b;
564 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
565 1.36 rillig bsp->b = 0;
566 1.1 rillig }
567 1.1 rillig
568 1.4 rillig int
569 1.8 rillig strict_bool_operand_binary(bool b, int i)
570 1.1 rillig {
571 1.1 rillig
572 1.4 rillig /* The right-hand sides of these assignments are ok. */
573 1.1 rillig b = !b;
574 1.1 rillig b = b && b;
575 1.1 rillig b = b || b;
576 1.1 rillig
577 1.4 rillig /*
578 1.4 rillig * The right-hand sides of these assignments implicitly convert from
579 1.4 rillig * scalar to bool.
580 1.4 rillig */
581 1.36 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
582 1.36 rillig b = !i;
583 1.36 rillig /* expect+2: error: left operand of '&&' must be bool, not 'int' [331] */
584 1.36 rillig /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */
585 1.36 rillig b = i && i;
586 1.36 rillig /* expect+2: error: left operand of '||' must be bool, not 'int' [331] */
587 1.36 rillig /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */
588 1.36 rillig b = i || i;
589 1.36 rillig
590 1.36 rillig /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */
591 1.36 rillig b = b && 0;
592 1.36 rillig /* expect+1: error: left operand of '&&' must be bool, not 'int' [331] */
593 1.36 rillig b = 0 && b;
594 1.36 rillig /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */
595 1.36 rillig b = b || 0;
596 1.36 rillig /* expect+1: error: left operand of '||' must be bool, not 'int' [331] */
597 1.36 rillig b = 0 || b;
598 1.4 rillig
599 1.4 rillig return i;
600 1.1 rillig }
601 1.1 rillig
602 1.1 rillig void
603 1.29 rillig strict_bool_operand_unary_all(bool b)
604 1.1 rillig {
605 1.8 rillig b = !b;
606 1.36 rillig /* expect+1: error: operand of '~' must not be bool [335] */
607 1.36 rillig b = ~b;
608 1.36 rillig /* expect+1: error: operand of '++x' must not be bool [335] */
609 1.36 rillig ++b;
610 1.36 rillig /* expect+1: error: operand of '--x' must not be bool [335] */
611 1.36 rillig --b;
612 1.36 rillig /* expect+1: error: operand of 'x++' must not be bool [335] */
613 1.36 rillig b++;
614 1.36 rillig /* expect+1: error: operand of 'x--' must not be bool [335] */
615 1.36 rillig b--;
616 1.36 rillig /* expect+1: error: operand of '+' must not be bool [335] */
617 1.36 rillig b = +b;
618 1.36 rillig /* expect+1: error: operand of '-' must not be bool [335] */
619 1.36 rillig b = -b;
620 1.29 rillig }
621 1.4 rillig
622 1.29 rillig void
623 1.29 rillig strict_bool_operand_binary_all(bool b, unsigned u)
624 1.29 rillig {
625 1.36 rillig /* expect+2: error: left operand of '*' must not be bool [336] */
626 1.36 rillig /* expect+1: error: right operand of '*' must not be bool [337] */
627 1.36 rillig b = b * b;
628 1.36 rillig /* expect+2: error: left operand of '/' must not be bool [336] */
629 1.36 rillig /* expect+1: error: right operand of '/' must not be bool [337] */
630 1.36 rillig b = b / b;
631 1.36 rillig /* expect+2: error: left operand of '%' must not be bool [336] */
632 1.36 rillig /* expect+1: error: right operand of '%' must not be bool [337] */
633 1.36 rillig b = b % b;
634 1.36 rillig /* expect+2: error: left operand of '+' must not be bool [336] */
635 1.36 rillig /* expect+1: error: right operand of '+' must not be bool [337] */
636 1.36 rillig b = b + b;
637 1.36 rillig /* expect+2: error: left operand of '-' must not be bool [336] */
638 1.36 rillig /* expect+1: error: right operand of '-' must not be bool [337] */
639 1.36 rillig b = b - b;
640 1.36 rillig /* expect+2: error: left operand of '<<' must not be bool [336] */
641 1.36 rillig /* expect+1: error: right operand of '<<' must not be bool [337] */
642 1.36 rillig b = b << b;
643 1.36 rillig /* expect+2: error: left operand of '>>' must not be bool [336] */
644 1.36 rillig /* expect+1: error: right operand of '>>' must not be bool [337] */
645 1.36 rillig b = b >> b;
646 1.36 rillig
647 1.36 rillig /* expect+2: error: left operand of '<' must not be bool [336] */
648 1.36 rillig /* expect+1: error: right operand of '<' must not be bool [337] */
649 1.36 rillig b = b < b;
650 1.36 rillig /* expect+2: error: left operand of '<=' must not be bool [336] */
651 1.36 rillig /* expect+1: error: right operand of '<=' must not be bool [337] */
652 1.36 rillig b = b <= b;
653 1.36 rillig /* expect+2: error: left operand of '>' must not be bool [336] */
654 1.36 rillig /* expect+1: error: right operand of '>' must not be bool [337] */
655 1.36 rillig b = b > b;
656 1.36 rillig /* expect+2: error: left operand of '>=' must not be bool [336] */
657 1.36 rillig /* expect+1: error: right operand of '>=' must not be bool [337] */
658 1.36 rillig b = b >= b;
659 1.8 rillig b = b == b;
660 1.8 rillig b = b != b;
661 1.1 rillig
662 1.8 rillig b = b & b;
663 1.8 rillig b = b ^ b;
664 1.8 rillig b = b | b;
665 1.8 rillig b = b && b;
666 1.8 rillig b = b || b;
667 1.8 rillig b = b ? b : b;
668 1.1 rillig
669 1.8 rillig b = b;
670 1.36 rillig /* expect+2: error: left operand of '*=' must not be bool [336] */
671 1.36 rillig /* expect+1: error: right operand of '*=' must not be bool [337] */
672 1.36 rillig b *= b;
673 1.36 rillig /* expect+2: error: left operand of '/=' must not be bool [336] */
674 1.36 rillig /* expect+1: error: right operand of '/=' must not be bool [337] */
675 1.36 rillig b /= b;
676 1.36 rillig /* expect+2: error: left operand of '%=' must not be bool [336] */
677 1.36 rillig /* expect+1: error: right operand of '%=' must not be bool [337] */
678 1.36 rillig b %= b;
679 1.36 rillig /* expect+2: error: left operand of '+=' must not be bool [336] */
680 1.36 rillig /* expect+1: error: right operand of '+=' must not be bool [337] */
681 1.36 rillig b += b;
682 1.36 rillig /* expect+2: error: left operand of '-=' must not be bool [336] */
683 1.36 rillig /* expect+1: error: right operand of '-=' must not be bool [337] */
684 1.36 rillig b -= b;
685 1.36 rillig /* expect+2: error: left operand of '<<=' must not be bool [336] */
686 1.36 rillig /* expect+1: error: right operand of '<<=' must not be bool [337] */
687 1.36 rillig b <<= b;
688 1.36 rillig /* expect+2: error: left operand of '>>=' must not be bool [336] */
689 1.36 rillig /* expect+1: error: right operand of '>>=' must not be bool [337] */
690 1.36 rillig b >>= b;
691 1.8 rillig b &= b;
692 1.8 rillig b ^= b;
693 1.8 rillig b |= b;
694 1.1 rillig
695 1.1 rillig /* Operations with mixed types. */
696 1.36 rillig /* expect+1: error: left operand of '*' must not be bool [336] */
697 1.36 rillig u = b * u;
698 1.36 rillig /* expect+1: error: right operand of '*' must not be bool [337] */
699 1.36 rillig u = u * b;
700 1.36 rillig /* expect+1: error: left operand of '/' must not be bool [336] */
701 1.36 rillig u = b / u;
702 1.36 rillig /* expect+1: error: right operand of '/' must not be bool [337] */
703 1.36 rillig u = u / b;
704 1.36 rillig /* expect+1: error: left operand of '%' must not be bool [336] */
705 1.36 rillig u = b % u;
706 1.36 rillig /* expect+1: error: right operand of '%' must not be bool [337] */
707 1.36 rillig u = u % b;
708 1.36 rillig /* expect+1: error: left operand of '+' must not be bool [336] */
709 1.36 rillig u = b + u;
710 1.36 rillig /* expect+1: error: right operand of '+' must not be bool [337] */
711 1.36 rillig u = u + b;
712 1.36 rillig /* expect+1: error: left operand of '-' must not be bool [336] */
713 1.36 rillig u = b - u;
714 1.36 rillig /* expect+1: error: right operand of '-' must not be bool [337] */
715 1.36 rillig u = u - b;
716 1.36 rillig /* expect+1: error: left operand of '<<' must not be bool [336] */
717 1.36 rillig u = b << u;
718 1.36 rillig /* expect+1: error: right operand of '<<' must not be bool [337] */
719 1.36 rillig u = u << b;
720 1.36 rillig /* expect+1: error: left operand of '>>' must not be bool [336] */
721 1.36 rillig u = b >> u;
722 1.36 rillig /* expect+1: error: right operand of '>>' must not be bool [337] */
723 1.36 rillig u = u >> b;
724 1.8 rillig u = b ? u : u;
725 1.36 rillig /* expect+1: error: operands of ':' have incompatible types (_Bool != unsigned int) [107] */
726 1.36 rillig u = b ? b : u;
727 1.36 rillig /* expect+1: error: operands of ':' have incompatible types (unsigned int != _Bool) [107] */
728 1.36 rillig u = b ? u : b;
729 1.1 rillig }
730 1.1 rillig
731 1.8 rillig bool
732 1.8 rillig strict_bool_operand_binary_comma(bool b, int i)
733 1.1 rillig {
734 1.36 rillig /* expect+1: warning: expression has null effect [129] */
735 1.36 rillig b = (b, !b);
736 1.36 rillig /* expect+1: warning: expression has null effect [129] */
737 1.36 rillig i = (i, i + 1);
738 1.8 rillig return b;
739 1.1 rillig }
740 1.1 rillig
741 1.8 rillig /*
742 1.8 rillig * strict-bool-operator-result:
743 1.8 rillig * The result type of the operators '!', '<', '<=', '>', '>=',
744 1.8 rillig * '==', '!=', '&&', '||' is _Bool instead of int.
745 1.8 rillig */
746 1.1 rillig
747 1.8 rillig void
748 1.8 rillig strict_bool_operator_result(bool b)
749 1.8 rillig {
750 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (char != _Bool) [107] */
751 1.36 rillig char c = b;
752 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (int != _Bool) [107] */
753 1.36 rillig int i = b;
754 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (double != _Bool) [107] */
755 1.36 rillig double d = b;
756 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (pointer != _Bool) [107] */
757 1.36 rillig void *p = b;
758 1.1 rillig
759 1.8 rillig /* The right-hand sides of these assignments are all ok. */
760 1.8 rillig b = !b;
761 1.8 rillig b = i == i;
762 1.8 rillig b = i != i;
763 1.8 rillig b = i < i;
764 1.8 rillig b = i <= i;
765 1.8 rillig b = i >= i;
766 1.8 rillig b = i > i;
767 1.8 rillig b = b && b;
768 1.8 rillig b = b || b;
769 1.1 rillig
770 1.1 rillig /*
771 1.8 rillig * The right-hand sides of these assignments are not ok, they
772 1.8 rillig * implicitly convert from bool to int.
773 1.1 rillig */
774 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
775 1.36 rillig i = !b;
776 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
777 1.36 rillig i = i == i;
778 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
779 1.36 rillig i = i != i;
780 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
781 1.36 rillig i = i < i;
782 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
783 1.36 rillig i = i <= i;
784 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
785 1.36 rillig i = i >= i;
786 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
787 1.36 rillig i = i > i;
788 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
789 1.36 rillig i = b && b;
790 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (int != _Bool) [107] */
791 1.36 rillig i = b || b;
792 1.8 rillig }
793 1.1 rillig
794 1.2 rillig
795 1.3 rillig /*
796 1.8 rillig * strict-bool-bitwise-and:
797 1.8 rillig * Expressions of the form "flags & FLAG" are compatible with _Bool if
798 1.8 rillig * the left operand has enum type, the right operand is an integer
799 1.8 rillig * constant and the resulting value is used in a context where it is
800 1.8 rillig * implicitly and immediately compared to zero.
801 1.8 rillig *
802 1.8 rillig * Note: Examples for such contexts are controlling expressions or the
803 1.8 rillig * operands of the operators '!', '&&', '||'.
804 1.8 rillig *
805 1.8 rillig * Note: Counterexamples for contexts are assignments to a bool variable.
806 1.8 rillig *
807 1.8 rillig * Note: These rules ensure that conforming code can be compiled without
808 1.8 rillig * change in behavior using old compilers that implement bool as an
809 1.8 rillig * ordinary integer type, without the special rule C99 6.3.1.2.
810 1.3 rillig */
811 1.3 rillig
812 1.3 rillig enum Flags {
813 1.3 rillig FLAG0 = 1 << 0,
814 1.3 rillig FLAG1 = 1 << 1,
815 1.3 rillig FLAG28 = 1 << 28
816 1.2 rillig };
817 1.2 rillig
818 1.36 rillig /* expect+2: warning: argument 'flags' unused in function 'strict_bool_bitwise_and_enum' [231] */
819 1.3 rillig void
820 1.36 rillig strict_bool_bitwise_and_enum(enum Flags flags)
821 1.3 rillig {
822 1.3 rillig bool b;
823 1.3 rillig
824 1.3 rillig /*
825 1.4 rillig * FLAG0 has the value 1 and thus can be stored in a bool variable
826 1.4 rillig * without truncation. Nevertheless this special case is not allowed
827 1.4 rillig * because it would be too confusing if FLAG0 would work and all the
828 1.4 rillig * other flags wouldn't.
829 1.3 rillig */
830 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
831 1.36 rillig b = flags & FLAG0;
832 1.3 rillig
833 1.3 rillig /*
834 1.3 rillig * Assuming that FLAG1 is set in flags, a _Bool variable stores this
835 1.4 rillig * as 1, as defined by C99 6.3.1.2. A uint8_t variable would store
836 1.4 rillig * it as 2, as that is the integer value of FLAG1. Since FLAG1 fits
837 1.4 rillig * in a uint8_t, no truncation takes place.
838 1.3 rillig */
839 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
840 1.36 rillig b = flags & FLAG1;
841 1.3 rillig
842 1.3 rillig /*
843 1.4 rillig * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
844 1.4 rillig * zero. In a uint8_t, the stored value would be 0 since bit 28 is
845 1.4 rillig * out of range for a uint8_t and thus gets truncated.
846 1.3 rillig */
847 1.36 rillig /* expect+1: error: operands of '=' have incompatible types (_Bool != int) [107] */
848 1.36 rillig b = flags & FLAG28;
849 1.3 rillig }
850 1.3 rillig
851 1.4 rillig /*
852 1.8 rillig * Demonstrate idiomatic code to query flags from an enum bit set.
853 1.8 rillig *
854 1.8 rillig * In all the controlling expressions in this function, the result of the
855 1.8 rillig * operator '&' is compared against 0. This makes this pattern work, no
856 1.8 rillig * matter whether the bits are in the low-value range or in the high-value
857 1.8 rillig * range (such as FLAG28, which has the value 1073741824, which is more than
858 1.8 rillig * what would fit into an unsigned char). Even if an enum could be extended
859 1.8 rillig * to larger types than int, this pattern would work.
860 1.4 rillig */
861 1.4 rillig void
862 1.8 rillig query_flag_from_enum_bit_set(enum Flags flags)
863 1.4 rillig {
864 1.8 rillig if (flags & FLAG0)
865 1.8 rillig println("FLAG0 is set");
866 1.4 rillig
867 1.8 rillig if ((flags & FLAG1) != 0)
868 1.8 rillig println("FLAG1 is set");
869 1.4 rillig
870 1.8 rillig if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
871 1.8 rillig println("FLAG0 and FLAG1 are both set");
872 1.4 rillig
873 1.8 rillig if (flags & FLAG0 && flags & FLAG1)
874 1.8 rillig println("FLAG0 and FLAG1 are both set");
875 1.4 rillig
876 1.8 rillig if ((flags & (FLAG0 | FLAG1)) != 0)
877 1.8 rillig println("At least one of FLAG0 and FLAG1 is set");
878 1.4 rillig
879 1.8 rillig if (flags & FLAG28)
880 1.8 rillig println("FLAG28 is set");
881 1.7 rillig }
882 1.10 rillig
883 1.10 rillig
884 1.12 rillig void
885 1.10 rillig strict_bool_operator_eq_bool_int(void)
886 1.10 rillig {
887 1.36 rillig /* expect+1: error: operands of '==' have incompatible types (_Bool != int) [107] */
888 1.36 rillig (void)(strict_bool_conversion_return_false() == 0);
889 1.10 rillig }
890 1.13 rillig
891 1.13 rillig void
892 1.13 rillig strict_bool_assign_bit_field_then_compare(void)
893 1.13 rillig {
894 1.13 rillig struct s {
895 1.13 rillig bool flag: 1;
896 1.13 rillig };
897 1.13 rillig
898 1.13 rillig struct s s = { __lint_false };
899 1.13 rillig
900 1.36 rillig /* expect+1: warning: expression has null effect [129] */
901 1.36 rillig (void)((s.flag = s.flag) != __lint_false);
902 1.13 rillig }
903 1.18 rillig
904 1.18 rillig void
905 1.18 rillig bool_as_array_index(bool cond)
906 1.18 rillig {
907 1.18 rillig static const char *repr[] = { "no", "yes" };
908 1.18 rillig /*
909 1.18 rillig * The '+' in the error message reveals that lint internally
910 1.18 rillig * translates 'arr[ind]' to '*(arr + ind)' in an early stage of
911 1.18 rillig * parsing.
912 1.18 rillig */
913 1.36 rillig /* expect+1: error: right operand of '+' must not be bool [337] */
914 1.36 rillig println(repr[cond]);
915 1.18 rillig println(cond ? "yes" : "no");
916 1.18 rillig }
917 1.20 rillig
918 1.20 rillig void
919 1.20 rillig do_while_false(void)
920 1.20 rillig {
921 1.20 rillig do {
922 1.20 rillig
923 1.21 rillig } while (__lint_false);
924 1.20 rillig }
925 1.20 rillig
926 1.20 rillig void
927 1.20 rillig do_while_true(void)
928 1.20 rillig {
929 1.20 rillig do {
930 1.20 rillig
931 1.36 rillig } while (__lint_true);
932 1.36 rillig /* expect-1: warning: constant in conditional context [161] */
933 1.20 rillig }
934 1.23 rillig
935 1.23 rillig void
936 1.23 rillig initialization(void)
937 1.23 rillig {
938 1.23 rillig struct {
939 1.23 rillig _Bool b;
940 1.23 rillig } var[] = {
941 1.23 rillig { __lint_false },
942 1.23 rillig { __lint_true },
943 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (_Bool != int) [107] */
944 1.36 rillig { 0 },
945 1.36 rillig /* expect+1: error: operands of 'init' have incompatible types (_Bool != int) [107] */
946 1.36 rillig { 1 },
947 1.23 rillig };
948 1.23 rillig }
949 1.31 rillig
950 1.32 rillig /*
951 1.32 rillig * For expressions that originate from a system header, the strict type rules
952 1.32 rillig * are relaxed a bit, to allow for expressions like 'flags & FLAG', even
953 1.32 rillig * though they are not strictly boolean.
954 1.32 rillig *
955 1.32 rillig * This shouldn't apply to function call expressions though since one of the
956 1.34 rillig * goals of strict bool mode is to normalize all expressions calling 'strcmp'
957 1.34 rillig * to be of the form 'strcmp(a, b) == 0' instead of '!strcmp(a, b)'.
958 1.32 rillig */
959 1.31 rillig # 1 "stdio.h" 1 3 4
960 1.31 rillig typedef struct stdio_file {
961 1.31 rillig int fd;
962 1.31 rillig } FILE;
963 1.31 rillig int ferror(FILE *);
964 1.31 rillig FILE stdio_files[3];
965 1.31 rillig FILE *stdio_stdout;
966 1.36 rillig # 967 "d_c99_bool_strict.c" 2
967 1.31 rillig # 1 "string.h" 1 3 4
968 1.31 rillig int strcmp(const char *, const char *);
969 1.36 rillig # 970 "d_c99_bool_strict.c" 2
970 1.31 rillig
971 1.31 rillig void
972 1.31 rillig controlling_expression(FILE *f, const char *a, const char *b)
973 1.31 rillig {
974 1.31 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
975 1.31 rillig if (ferror(f))
976 1.31 rillig return;
977 1.31 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
978 1.31 rillig if (strcmp(a, b))
979 1.31 rillig return;
980 1.31 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
981 1.31 rillig if (!ferror(f))
982 1.31 rillig return;
983 1.31 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
984 1.31 rillig if (!strcmp(a, b))
985 1.31 rillig return;
986 1.31 rillig
987 1.31 rillig /*
988 1.34 rillig * Before tree.c 1.395 from 2021-11-16, the expression below didn't
989 1.35 rillig * produce a warning since the expression 'stdio_files' came from a
990 1.35 rillig * system header (via a macro), and this property was passed up to
991 1.35 rillig * the expression 'ferror(stdio_files[1])'.
992 1.31 rillig *
993 1.34 rillig * That was wrong though since the type of a function call expression
994 1.34 rillig * only depends on the function itself but not its arguments types.
995 1.34 rillig * The old rule had allowed a raw condition 'strcmp(a, b)' without
996 1.34 rillig * the comparison '!= 0', as long as one of its arguments came from a
997 1.34 rillig * system header.
998 1.31 rillig *
999 1.31 rillig * Seen in bin/echo/echo.c, function main, call to ferror.
1000 1.31 rillig */
1001 1.34 rillig /* expect+5: error: controlling expression must be bool, not 'int' [333] */
1002 1.31 rillig if (ferror(
1003 1.36 rillig # 1004 "d_c99_bool_strict.c" 3 4
1004 1.31 rillig &stdio_files[1]
1005 1.36 rillig # 1006 "d_c99_bool_strict.c"
1006 1.31 rillig ))
1007 1.31 rillig return;
1008 1.31 rillig
1009 1.31 rillig /*
1010 1.33 rillig * Before cgram.y 1.369 from 2021-11-16, at the end of parsing the
1011 1.33 rillig * name 'stdio_stdout', the parser already looked ahead to the next
1012 1.34 rillig * token, to see whether it was the '(' of a function call.
1013 1.34 rillig *
1014 1.34 rillig * At that point, the parser was no longer in a system header,
1015 1.34 rillig * therefore 'stdio_stdout' had tn_sys == false, and this information
1016 1.34 rillig * was pushed down to the whole function call expression (which was
1017 1.34 rillig * another bug that got fixed in tree.c 1.395 from 2021-11-16).
1018 1.31 rillig */
1019 1.34 rillig /* expect+5: error: controlling expression must be bool, not 'int' [333] */
1020 1.31 rillig if (ferror(
1021 1.36 rillig # 1022 "d_c99_bool_strict.c" 3 4
1022 1.31 rillig stdio_stdout
1023 1.36 rillig # 1024 "d_c99_bool_strict.c"
1024 1.32 rillig ))
1025 1.32 rillig return;
1026 1.32 rillig
1027 1.32 rillig /*
1028 1.34 rillig * In this variant of the pattern, there is a token ')' after the
1029 1.34 rillig * name 'stdio_stdout', which even before tree.c 1.395 from
1030 1.34 rillig * 2021-11-16 had the effect that at the end of parsing the name, the
1031 1.34 rillig * parser was still in the system header, thus setting tn_sys (or
1032 1.34 rillig * rather tn_relaxed at that time) to true.
1033 1.32 rillig */
1034 1.34 rillig /* expect+5: error: controlling expression must be bool, not 'int' [333] */
1035 1.32 rillig if (ferror(
1036 1.36 rillig # 1037 "d_c99_bool_strict.c" 3 4
1037 1.32 rillig (stdio_stdout)
1038 1.36 rillig # 1039 "d_c99_bool_strict.c"
1039 1.32 rillig ))
1040 1.32 rillig return;
1041 1.32 rillig
1042 1.32 rillig /*
1043 1.33 rillig * Before cgram.y 1.369 from 2021-11-16, the comment following
1044 1.33 rillig * 'stdio_stdout' did not prevent the search for '('. At the point
1045 1.37 rillig * where build_name called expr_alloc_tnode, the parser was already
1046 1.33 rillig * in the main file again, thus treating 'stdio_stdout' as not coming
1047 1.33 rillig * from a system header.
1048 1.34 rillig *
1049 1.34 rillig * This has been fixed in tree.c 1.395 from 2021-11-16. Before that,
1050 1.34 rillig * an expression had come from a system header if its operands came
1051 1.34 rillig * from a system header, but that was only close to the truth. In a
1052 1.34 rillig * case where both operands come from a system header but the
1053 1.34 rillig * operator comes from the main translation unit, the main
1054 1.34 rillig * translation unit still has control over the whole expression. So
1055 1.34 rillig * the correct approach is to focus on the operator, not the
1056 1.34 rillig * operands. There are a few corner cases where the operator is
1057 1.34 rillig * invisible (for implicit conversions) or synthetic (for translating
1058 1.34 rillig * 'arr[index]' to '*(arr + index)', but these are handled as well.
1059 1.32 rillig */
1060 1.34 rillig /* expect+5: error: controlling expression must be bool, not 'int' [333] */
1061 1.32 rillig if (ferror(
1062 1.36 rillig # 1063 "d_c99_bool_strict.c" 3 4
1063 1.32 rillig stdio_stdout /* comment */
1064 1.36 rillig # 1065 "d_c99_bool_strict.c"
1065 1.31 rillig ))
1066 1.31 rillig return;
1067 1.31 rillig }
1068