d_c99_bool_strict.c revision 1.31 1 1.31 rillig /* $NetBSD: d_c99_bool_strict.c,v 1.31 2021/11/14 11:23:52 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.9 rillig accept_bool(0); /* expect: 334 */
128 1.9 rillig accept_bool(1); /* expect: 334 */
129 1.8 rillig accept_bool(2); /* expect: 334 */
130 1.8 rillig }
131 1.8 rillig
132 1.8 rillig enum strict_bool_constant_expressions {
133 1.8 rillig /* Ok: __lint_false is a boolean constant expression. */
134 1.19 rillig FALSE = __lint_false ? 100 : 101, /* expect: 161 */
135 1.8 rillig
136 1.8 rillig /* Ok: __lint_true is a boolean constant expression. */
137 1.19 rillig TRUE = __lint_true ? 100 : 101, /* expect: 161 */
138 1.8 rillig
139 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
140 1.9 rillig INT0 = 0 ? 100 : 101, /* expect: 331 */
141 1.8 rillig
142 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
143 1.9 rillig INT1 = 1 ? 100 : 101, /* expect: 331 */
144 1.8 rillig
145 1.8 rillig /* Not ok: 2 is not a boolean constant. */
146 1.8 rillig INT2 = 2 ? 100 : 101, /* expect: 331 */
147 1.8 rillig
148 1.8 rillig /* Not ok: compound integer expressions are not bool. */
149 1.9 rillig ARITH = (2 - 2) ? 100 : 101, /* expect: 331 */
150 1.8 rillig
151 1.8 rillig /*
152 1.8 rillig * Without strict bool mode, these two variants of an expression can
153 1.8 rillig * occur when a preprocessor macro is either defined to 1 or left
154 1.27 rillig * empty (since C99), as in lint1/ops.def.
155 1.8 rillig *
156 1.27 rillig * In strict bool mode, the resulting expression can be compared
157 1.27 rillig * against 0 to achieve the same effect (so +0 != 0 or 1 + 0 != 0).
158 1.8 rillig */
159 1.9 rillig BINARY_PLUS = (1 + 0) ? 100 : 101, /* expect: 331 */
160 1.9 rillig UNARY_PLUS = (+0) ? 100 : 101, /* expect: 331 */
161 1.8 rillig
162 1.8 rillig /* The main operator '>' has return type bool. */
163 1.19 rillig Q1 = (13 > 12) ? 100 : 101, /* expect: 161 */
164 1.8 rillig
165 1.8 rillig /*
166 1.8 rillig * The parenthesized expression has type int and thus cannot be
167 1.8 rillig * used as the controlling expression in the '?:' operator.
168 1.8 rillig */
169 1.28 rillig Q2 = (13 > 12 ? 1 : 7) ? 100 : 101, /* expect: 161 *//* expect: 331 */
170 1.8 rillig
171 1.15 rillig BINAND_BOOL = __lint_false & __lint_true, /* expect: 55 */
172 1.8 rillig BINAND_INT = 0 & 1,
173 1.8 rillig
174 1.15 rillig BINXOR_BOOL = __lint_false ^ __lint_true, /* expect: 55 */
175 1.8 rillig BINXOR_INT = 0 ^ 1,
176 1.8 rillig
177 1.15 rillig BINOR_BOOL = __lint_false | __lint_true, /* expect: 55 */
178 1.8 rillig BINOR_INT = 0 | 1,
179 1.8 rillig
180 1.28 rillig LOGOR_BOOL = __lint_false || __lint_true, /* expect: 161 *//* expect: 55 */
181 1.28 rillig LOGOR_INT = 0 || 1, /* expect: 331 *//* expect: 332 */
182 1.8 rillig
183 1.28 rillig LOGAND_BOOL = __lint_false && __lint_true, /* expect: 161 *//* expect: 55 */
184 1.28 rillig LOGAND_INT = 0 && 1, /* expect: 331 *//* expect: 332 */
185 1.8 rillig };
186 1.8 rillig
187 1.8 rillig /*
188 1.8 rillig * strict-bool-bit-fields
189 1.8 rillig */
190 1.8 rillig
191 1.8 rillig void
192 1.8 rillig strict_bool_bit_fields(void)
193 1.8 rillig {
194 1.8 rillig struct flags {
195 1.8 rillig bool bool_flag: 1;
196 1.8 rillig unsigned uint_flag: 1;
197 1.8 rillig };
198 1.8 rillig
199 1.8 rillig struct flags flags = { __lint_false, 0 };
200 1.8 rillig struct flags *flags_ptr = &flags;
201 1.8 rillig bool b;
202 1.8 rillig
203 1.8 rillig b = flags.bool_flag;
204 1.8 rillig b = flags.uint_flag; /* expect: 107 */
205 1.8 rillig flags.bool_flag = b;
206 1.8 rillig flags.uint_flag = b; /* expect: 107 */
207 1.8 rillig
208 1.8 rillig b = flags_ptr->bool_flag;
209 1.8 rillig b = flags_ptr->uint_flag; /* expect: 107 */
210 1.8 rillig flags_ptr->bool_flag = b;
211 1.8 rillig flags_ptr->uint_flag = b; /* expect: 107 */
212 1.8 rillig }
213 1.8 rillig
214 1.8 rillig void
215 1.8 rillig strict_bool_bit_fields_operand_conversion(void)
216 1.8 rillig {
217 1.8 rillig struct s {
218 1.8 rillig bool ordinary;
219 1.8 rillig bool bit_field: 1;
220 1.8 rillig };
221 1.8 rillig
222 1.24 rillig struct s s = { 0 > 0 };
223 1.8 rillig
224 1.8 rillig s.ordinary = s.ordinary | s.ordinary;
225 1.15 rillig s.bit_field = s.bit_field | s.bit_field;
226 1.8 rillig }
227 1.8 rillig
228 1.8 rillig /*
229 1.8 rillig * strict-bool-conversion
230 1.8 rillig */
231 1.8 rillig
232 1.8 rillig bool
233 1.8 rillig strict_bool_conversion_return_false(void)
234 1.8 rillig {
235 1.8 rillig return __lint_false;
236 1.8 rillig }
237 1.8 rillig
238 1.8 rillig bool
239 1.8 rillig strict_bool_conversion_return_true(void)
240 1.8 rillig {
241 1.8 rillig return __lint_true;
242 1.8 rillig }
243 1.8 rillig
244 1.8 rillig bool
245 1.8 rillig strict_bool_conversion_return_bool(bool b)
246 1.8 rillig {
247 1.8 rillig return b;
248 1.8 rillig }
249 1.8 rillig
250 1.8 rillig bool
251 1.8 rillig strict_bool_conversion_return_0(void)
252 1.8 rillig {
253 1.9 rillig return 0; /* expect: 211 */
254 1.8 rillig }
255 1.8 rillig
256 1.8 rillig bool
257 1.8 rillig strict_bool_conversion_return_1(void)
258 1.8 rillig {
259 1.9 rillig return 1; /* expect: 211 */
260 1.8 rillig }
261 1.8 rillig
262 1.8 rillig bool
263 1.8 rillig strict_bool_conversion_return_2(void)
264 1.8 rillig {
265 1.8 rillig return 2; /* expect: 211 */
266 1.8 rillig }
267 1.8 rillig
268 1.8 rillig bool
269 1.8 rillig strict_bool_conversion_return_pointer(const void *p) /* expect: 231 */
270 1.8 rillig {
271 1.8 rillig return p; /* expect: 211 */
272 1.8 rillig }
273 1.8 rillig
274 1.8 rillig char
275 1.8 rillig strict_bool_conversion_return_false_as_char(void)
276 1.8 rillig {
277 1.8 rillig return __lint_false; /* expect: 211 */
278 1.8 rillig }
279 1.8 rillig
280 1.8 rillig char
281 1.8 rillig strict_bool_conversion_return_true_as_char(void)
282 1.8 rillig {
283 1.8 rillig return __lint_true; /* expect: 211 */
284 1.8 rillig }
285 1.8 rillig
286 1.8 rillig
287 1.1 rillig void
288 1.8 rillig strict_bool_conversion_function_argument(void)
289 1.1 rillig {
290 1.8 rillig accept_bool(__lint_false);
291 1.8 rillig accept_bool(__lint_true);
292 1.8 rillig }
293 1.8 rillig
294 1.8 rillig void
295 1.8 rillig strict_bool_conversion_function_argument_pass(bool b, int i, const char *p)
296 1.8 rillig {
297 1.8 rillig /* No conversion necessary. */
298 1.8 rillig take_arguments(b, i, p);
299 1.8 rillig
300 1.8 rillig /* Implicitly converting bool to other scalar types. */
301 1.28 rillig take_arguments(b, b, b); /* expect: 334 *//* expect: 334 */
302 1.8 rillig
303 1.8 rillig /* Implicitly converting int to bool (arg #1). */
304 1.28 rillig take_arguments(i, i, i); /* expect: 334 *//* expect: 154 */
305 1.8 rillig
306 1.8 rillig /* Implicitly converting pointer to bool (arg #1). */
307 1.28 rillig take_arguments(p, p, p); /* expect: 334 *//* expect: 154 */
308 1.8 rillig
309 1.8 rillig /* Passing bool as vararg. */
310 1.22 rillig take_arguments(b, i, p, b, i, p); /* TODO: expect: arg#4 */
311 1.8 rillig
312 1.8 rillig /* Passing a bool constant. */
313 1.8 rillig take_arguments(__lint_false, i, p);
314 1.8 rillig
315 1.8 rillig /* Passing a bool constant. */
316 1.8 rillig take_arguments(__lint_true, i, p);
317 1.8 rillig
318 1.8 rillig /* Trying to pass integer constants. */
319 1.9 rillig take_arguments(0, i, p); /* expect: 334 */
320 1.9 rillig take_arguments(1, i, p); /* expect: 334 */
321 1.8 rillig take_arguments(2, i, p); /* expect: 334 */
322 1.8 rillig }
323 1.1 rillig
324 1.8 rillig void
325 1.8 rillig strict_bool_conversion_between_bool_and_int(void)
326 1.8 rillig {
327 1.8 rillig bool b;
328 1.8 rillig int i;
329 1.1 rillig
330 1.9 rillig b = 0; /* expect: 107 */
331 1.9 rillig b = __lint_false;
332 1.9 rillig b = 1; /* expect: 107 */
333 1.8 rillig b = __lint_true;
334 1.1 rillig
335 1.8 rillig i = 0;
336 1.8 rillig i = __lint_false; /* expect: 107 */
337 1.8 rillig i = 1;
338 1.8 rillig i = __lint_true; /* expect: 107 */
339 1.8 rillig
340 1.8 rillig i = b; /* expect: 107 */
341 1.8 rillig b = i; /* expect: 107 */
342 1.8 rillig }
343 1.8 rillig
344 1.8 rillig void
345 1.8 rillig strict_bool_conversion_from_bool_to_scalar(bool b) /* expect: 231 */
346 1.8 rillig {
347 1.8 rillig int i;
348 1.8 rillig unsigned u;
349 1.8 rillig double d;
350 1.8 rillig void *p;
351 1.8 rillig
352 1.8 rillig i = b; /* expect: 107 */
353 1.8 rillig u = b; /* expect: 107 */
354 1.8 rillig d = b; /* expect: 107 */
355 1.8 rillig p = b; /* expect: 107 */
356 1.8 rillig }
357 1.8 rillig
358 1.8 rillig /*
359 1.8 rillig * strict-bool-controlling-expression:
360 1.8 rillig * Controlling expressions in 'if', 'while', 'for', '?:' must be of
361 1.8 rillig * type bool.
362 1.8 rillig */
363 1.8 rillig
364 1.8 rillig void
365 1.8 rillig strict_bool_controlling_expression(bool b, int i, double d, const void *p)
366 1.8 rillig {
367 1.19 rillig if (__lint_false) /* expect: 161 */
368 1.26 rillig do_nothing(); /* expect: statement not reached */
369 1.8 rillig
370 1.19 rillig if (__lint_true) /* expect: 161 */
371 1.8 rillig do_nothing();
372 1.8 rillig
373 1.8 rillig if (b)
374 1.8 rillig do_nothing();
375 1.8 rillig
376 1.30 rillig if (/*CONSTCOND*/0) /* expect: 333 */
377 1.30 rillig do_nothing(); /* expect: statement not reached [193] */
378 1.8 rillig
379 1.30 rillig if (/*CONSTCOND*/1) /* expect: 333 */
380 1.8 rillig do_nothing();
381 1.8 rillig
382 1.30 rillig if (/*CONSTCOND*/2) /* expect: 333 */
383 1.8 rillig do_nothing();
384 1.1 rillig
385 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
386 1.4 rillig if (i) /* expect: 333 */
387 1.8 rillig do_nothing();
388 1.1 rillig if (i != 0)
389 1.8 rillig do_nothing();
390 1.1 rillig
391 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
392 1.4 rillig if (d) /* expect: 333 */
393 1.8 rillig do_nothing();
394 1.1 rillig if (d != 0.0)
395 1.8 rillig do_nothing();
396 1.1 rillig
397 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
398 1.4 rillig if (p) /* expect: 333 */
399 1.8 rillig do_nothing();
400 1.1 rillig if (p != (void *)0)
401 1.8 rillig do_nothing();
402 1.8 rillig }
403 1.1 rillig
404 1.8 rillig /*
405 1.8 rillig * strict-bool-operand-unary:
406 1.8 rillig * Operator bool? scalar?
407 1.8 rillig * ! yes -
408 1.8 rillig * & yes yes
409 1.25 rillig * The other unary operators do not accept bool operands.
410 1.8 rillig */
411 1.8 rillig
412 1.8 rillig void
413 1.8 rillig strict_bool_operand_unary_not(void)
414 1.8 rillig {
415 1.8 rillig bool b = __lint_false;
416 1.8 rillig
417 1.8 rillig b = !b;
418 1.8 rillig b = !!!b;
419 1.28 rillig b = !__lint_false; /* expect: 161 *//* expect: 239 */
420 1.28 rillig b = !__lint_true; /* expect: 161 *//* expect: 239 */
421 1.8 rillig
422 1.8 rillig int i = 0;
423 1.8 rillig
424 1.8 rillig i = !i; /* expect: 330 */
425 1.8 rillig i = !!!i; /* expect: 330 */
426 1.9 rillig i = !0; /* expect: 330 */
427 1.9 rillig i = !1; /* expect: 330 */
428 1.8 rillig }
429 1.8 rillig
430 1.8 rillig void
431 1.8 rillig strict_bool_operand_unary_address(void)
432 1.8 rillig {
433 1.8 rillig bool b = __lint_false;
434 1.8 rillig
435 1.8 rillig /* Taking the address of a bool lvalue. */
436 1.8 rillig bool *bp;
437 1.8 rillig bp = &b;
438 1.8 rillig *bp = b;
439 1.8 rillig b = *bp;
440 1.1 rillig }
441 1.1 rillig
442 1.29 rillig /* see strict_bool_operand_unary_all below for the other unary operators. */
443 1.29 rillig
444 1.8 rillig /*
445 1.8 rillig * strict-bool-operand-binary:
446 1.8 rillig * Operator left: bool? other? right: bool? other?
447 1.8 rillig * . - yes yes yes
448 1.8 rillig * -> - yes yes yes
449 1.11 rillig * <=, <, >=, > - yes - yes
450 1.8 rillig * ==, != yes yes yes yes
451 1.8 rillig * & yes yes yes yes
452 1.8 rillig * ^ yes yes yes yes
453 1.8 rillig * | yes yes yes yes
454 1.8 rillig * && yes - yes -
455 1.8 rillig * || yes - yes -
456 1.8 rillig * ? yes - yes yes
457 1.8 rillig * : yes yes yes yes
458 1.8 rillig * = yes yes yes yes
459 1.8 rillig * &=, ^=, |= yes yes yes yes
460 1.8 rillig * , yes yes yes yes
461 1.8 rillig * The other binary operators do not accept bool operands.
462 1.8 rillig */
463 1.8 rillig
464 1.8 rillig /*
465 1.8 rillig * Ensure that bool members can be accessed as usual.
466 1.8 rillig */
467 1.1 rillig void
468 1.8 rillig strict_bool_operand_binary_dot_arrow(void)
469 1.1 rillig {
470 1.8 rillig struct bool_struct {
471 1.8 rillig bool b;
472 1.8 rillig };
473 1.8 rillig
474 1.8 rillig /* Initialize and assign using boolean constants. */
475 1.8 rillig bool b = __lint_false;
476 1.8 rillig b = __lint_true;
477 1.1 rillig
478 1.8 rillig /* Access a struct member using the '.' operator. */
479 1.8 rillig struct bool_struct bs = { __lint_true };
480 1.8 rillig b = bs.b;
481 1.8 rillig bs.b = b;
482 1.9 rillig bs.b = 0; /* expect: 107 */
483 1.1 rillig
484 1.8 rillig /* Access a struct member using the '->' operator. */
485 1.8 rillig struct bool_struct *bsp = &bs;
486 1.8 rillig b = bsp->b;
487 1.8 rillig bsp->b = b;
488 1.9 rillig bsp->b = 0; /* expect: 107 */
489 1.1 rillig }
490 1.1 rillig
491 1.4 rillig int
492 1.8 rillig strict_bool_operand_binary(bool b, int i)
493 1.1 rillig {
494 1.1 rillig
495 1.4 rillig /* The right-hand sides of these assignments are ok. */
496 1.1 rillig b = !b;
497 1.1 rillig b = b && b;
498 1.1 rillig b = b || b;
499 1.1 rillig
500 1.4 rillig /*
501 1.4 rillig * The right-hand sides of these assignments implicitly convert from
502 1.4 rillig * scalar to bool.
503 1.4 rillig */
504 1.4 rillig b = !i; /* expect: 330 */
505 1.28 rillig b = i && i; /* expect: 331 *//* expect: 332 */
506 1.28 rillig b = i || i; /* expect: 331 *//* expect: 332 */
507 1.4 rillig
508 1.9 rillig b = b && 0; /* expect: 332 */
509 1.9 rillig b = 0 && b; /* expect: 331 */
510 1.9 rillig b = b || 0; /* expect: 332 */
511 1.9 rillig b = 0 || b; /* expect: 331 */
512 1.4 rillig
513 1.4 rillig return i;
514 1.1 rillig }
515 1.1 rillig
516 1.1 rillig void
517 1.29 rillig strict_bool_operand_unary_all(bool b)
518 1.1 rillig {
519 1.8 rillig b = !b;
520 1.4 rillig b = ~b; /* expect: 335 */
521 1.4 rillig ++b; /* expect: 335 */
522 1.4 rillig --b; /* expect: 335 */
523 1.4 rillig b++; /* expect: 335 */
524 1.4 rillig b--; /* expect: 335 */
525 1.4 rillig b = +b; /* expect: 335 */
526 1.4 rillig b = -b; /* expect: 335 */
527 1.29 rillig }
528 1.4 rillig
529 1.29 rillig void
530 1.29 rillig strict_bool_operand_binary_all(bool b, unsigned u)
531 1.29 rillig {
532 1.28 rillig b = b * b; /* expect: 336 *//* expect: 337 */
533 1.28 rillig b = b / b; /* expect: 336 *//* expect: 337 */
534 1.28 rillig b = b % b; /* expect: 336 *//* expect: 337 */
535 1.28 rillig b = b + b; /* expect: 336 *//* expect: 337 */
536 1.28 rillig b = b - b; /* expect: 336 *//* expect: 337 */
537 1.28 rillig b = b << b; /* expect: 336 *//* expect: 337 */
538 1.28 rillig b = b >> b; /* expect: 336 *//* expect: 337 */
539 1.28 rillig
540 1.28 rillig b = b < b; /* expect: 336 *//* expect: 337 */
541 1.28 rillig b = b <= b; /* expect: 336 *//* expect: 337 */
542 1.28 rillig b = b > b; /* expect: 336 *//* expect: 337 */
543 1.28 rillig b = b >= b; /* expect: 336 *//* expect: 337 */
544 1.8 rillig b = b == b;
545 1.8 rillig b = b != b;
546 1.1 rillig
547 1.8 rillig b = b & b;
548 1.8 rillig b = b ^ b;
549 1.8 rillig b = b | b;
550 1.8 rillig b = b && b;
551 1.8 rillig b = b || b;
552 1.8 rillig b = b ? b : b;
553 1.1 rillig
554 1.8 rillig b = b;
555 1.28 rillig b *= b; /* expect: 336 *//* expect: 337 */
556 1.28 rillig b /= b; /* expect: 336 *//* expect: 337 */
557 1.28 rillig b %= b; /* expect: 336 *//* expect: 337 */
558 1.28 rillig b += b; /* expect: 336 *//* expect: 337 */
559 1.28 rillig b -= b; /* expect: 336 *//* expect: 337 */
560 1.28 rillig b <<= b; /* expect: 336 *//* expect: 337 */
561 1.28 rillig b >>= b; /* expect: 336 *//* expect: 337 */
562 1.8 rillig b &= b;
563 1.8 rillig b ^= b;
564 1.8 rillig b |= b;
565 1.1 rillig
566 1.1 rillig /* Operations with mixed types. */
567 1.4 rillig u = b * u; /* expect: 336 */
568 1.4 rillig u = u * b; /* expect: 337 */
569 1.4 rillig u = b / u; /* expect: 336 */
570 1.4 rillig u = u / b; /* expect: 337 */
571 1.4 rillig u = b % u; /* expect: 336 */
572 1.4 rillig u = u % b; /* expect: 337 */
573 1.4 rillig u = b + u; /* expect: 336 */
574 1.4 rillig u = u + b; /* expect: 337 */
575 1.4 rillig u = b - u; /* expect: 336 */
576 1.4 rillig u = u - b; /* expect: 337 */
577 1.4 rillig u = b << u; /* expect: 336 */
578 1.4 rillig u = u << b; /* expect: 337 */
579 1.4 rillig u = b >> u; /* expect: 336 */
580 1.4 rillig u = u >> b; /* expect: 337 */
581 1.8 rillig u = b ? u : u;
582 1.4 rillig u = b ? b : u; /* expect: 107 */
583 1.4 rillig u = b ? u : b; /* expect: 107 */
584 1.1 rillig }
585 1.1 rillig
586 1.8 rillig bool
587 1.8 rillig strict_bool_operand_binary_comma(bool b, int i)
588 1.1 rillig {
589 1.19 rillig b = (b, !b); /* expect: 129 */
590 1.19 rillig i = (i, i + 1); /* expect: 129 */
591 1.8 rillig return b;
592 1.1 rillig }
593 1.1 rillig
594 1.8 rillig /*
595 1.8 rillig * strict-bool-operator-result:
596 1.8 rillig * The result type of the operators '!', '<', '<=', '>', '>=',
597 1.8 rillig * '==', '!=', '&&', '||' is _Bool instead of int.
598 1.8 rillig */
599 1.1 rillig
600 1.8 rillig void
601 1.8 rillig strict_bool_operator_result(bool b)
602 1.8 rillig {
603 1.8 rillig char c = b; /* expect: 107 */
604 1.8 rillig int i = b; /* expect: 107 */
605 1.8 rillig double d = b; /* expect: 107 */
606 1.8 rillig void *p = b; /* expect: 107 */
607 1.1 rillig
608 1.8 rillig /* The right-hand sides of these assignments are all ok. */
609 1.8 rillig b = !b;
610 1.8 rillig b = i == i;
611 1.8 rillig b = i != i;
612 1.8 rillig b = i < i;
613 1.8 rillig b = i <= i;
614 1.8 rillig b = i >= i;
615 1.8 rillig b = i > i;
616 1.8 rillig b = b && b;
617 1.8 rillig b = b || b;
618 1.1 rillig
619 1.1 rillig /*
620 1.8 rillig * The right-hand sides of these assignments are not ok, they
621 1.8 rillig * implicitly convert from bool to int.
622 1.1 rillig */
623 1.8 rillig i = !b; /* expect: 107 */
624 1.8 rillig i = i == i; /* expect: 107 */
625 1.8 rillig i = i != i; /* expect: 107 */
626 1.8 rillig i = i < i; /* expect: 107 */
627 1.8 rillig i = i <= i; /* expect: 107 */
628 1.8 rillig i = i >= i; /* expect: 107 */
629 1.8 rillig i = i > i; /* expect: 107 */
630 1.8 rillig i = b && b; /* expect: 107 */
631 1.8 rillig i = b || b; /* expect: 107 */
632 1.8 rillig }
633 1.1 rillig
634 1.2 rillig
635 1.3 rillig /*
636 1.8 rillig * strict-bool-bitwise-and:
637 1.8 rillig * Expressions of the form "flags & FLAG" are compatible with _Bool if
638 1.8 rillig * the left operand has enum type, the right operand is an integer
639 1.8 rillig * constant and the resulting value is used in a context where it is
640 1.8 rillig * implicitly and immediately compared to zero.
641 1.8 rillig *
642 1.8 rillig * Note: Examples for such contexts are controlling expressions or the
643 1.8 rillig * operands of the operators '!', '&&', '||'.
644 1.8 rillig *
645 1.8 rillig * Note: Counterexamples for contexts are assignments to a bool variable.
646 1.8 rillig *
647 1.8 rillig * Note: These rules ensure that conforming code can be compiled without
648 1.8 rillig * change in behavior using old compilers that implement bool as an
649 1.8 rillig * ordinary integer type, without the special rule C99 6.3.1.2.
650 1.3 rillig */
651 1.3 rillig
652 1.3 rillig enum Flags {
653 1.3 rillig FLAG0 = 1 << 0,
654 1.3 rillig FLAG1 = 1 << 1,
655 1.3 rillig FLAG28 = 1 << 28
656 1.2 rillig };
657 1.2 rillig
658 1.3 rillig void
659 1.8 rillig strict_bool_bitwise_and_enum(enum Flags flags) /* expect: 231 */
660 1.3 rillig {
661 1.3 rillig bool b;
662 1.3 rillig
663 1.3 rillig /*
664 1.4 rillig * FLAG0 has the value 1 and thus can be stored in a bool variable
665 1.4 rillig * without truncation. Nevertheless this special case is not allowed
666 1.4 rillig * because it would be too confusing if FLAG0 would work and all the
667 1.4 rillig * other flags wouldn't.
668 1.3 rillig */
669 1.4 rillig b = flags & FLAG0; /* expect: 107 */
670 1.3 rillig
671 1.3 rillig /*
672 1.3 rillig * Assuming that FLAG1 is set in flags, a _Bool variable stores this
673 1.4 rillig * as 1, as defined by C99 6.3.1.2. A uint8_t variable would store
674 1.4 rillig * it as 2, as that is the integer value of FLAG1. Since FLAG1 fits
675 1.4 rillig * in a uint8_t, no truncation takes place.
676 1.3 rillig */
677 1.4 rillig b = flags & FLAG1; /* expect: 107 */
678 1.3 rillig
679 1.3 rillig /*
680 1.4 rillig * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
681 1.4 rillig * zero. In a uint8_t, the stored value would be 0 since bit 28 is
682 1.4 rillig * out of range for a uint8_t and thus gets truncated.
683 1.3 rillig */
684 1.4 rillig b = flags & FLAG28; /* expect: 107 */
685 1.3 rillig }
686 1.3 rillig
687 1.4 rillig /*
688 1.8 rillig * Demonstrate idiomatic code to query flags from an enum bit set.
689 1.8 rillig *
690 1.8 rillig * In all the controlling expressions in this function, the result of the
691 1.8 rillig * operator '&' is compared against 0. This makes this pattern work, no
692 1.8 rillig * matter whether the bits are in the low-value range or in the high-value
693 1.8 rillig * range (such as FLAG28, which has the value 1073741824, which is more than
694 1.8 rillig * what would fit into an unsigned char). Even if an enum could be extended
695 1.8 rillig * to larger types than int, this pattern would work.
696 1.4 rillig */
697 1.4 rillig void
698 1.8 rillig query_flag_from_enum_bit_set(enum Flags flags)
699 1.4 rillig {
700 1.8 rillig if (flags & FLAG0)
701 1.8 rillig println("FLAG0 is set");
702 1.4 rillig
703 1.8 rillig if ((flags & FLAG1) != 0)
704 1.8 rillig println("FLAG1 is set");
705 1.4 rillig
706 1.8 rillig if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
707 1.8 rillig println("FLAG0 and FLAG1 are both set");
708 1.4 rillig
709 1.8 rillig if (flags & FLAG0 && flags & FLAG1)
710 1.8 rillig println("FLAG0 and FLAG1 are both set");
711 1.4 rillig
712 1.8 rillig if ((flags & (FLAG0 | FLAG1)) != 0)
713 1.8 rillig println("At least one of FLAG0 and FLAG1 is set");
714 1.4 rillig
715 1.8 rillig if (flags & FLAG28)
716 1.8 rillig println("FLAG28 is set");
717 1.7 rillig }
718 1.10 rillig
719 1.10 rillig
720 1.12 rillig void
721 1.10 rillig strict_bool_operator_eq_bool_int(void)
722 1.10 rillig {
723 1.12 rillig (void)(strict_bool_conversion_return_false() == 0); /* expect: 107 */
724 1.10 rillig }
725 1.13 rillig
726 1.13 rillig void
727 1.13 rillig strict_bool_assign_bit_field_then_compare(void)
728 1.13 rillig {
729 1.13 rillig struct s {
730 1.13 rillig bool flag: 1;
731 1.13 rillig };
732 1.13 rillig
733 1.13 rillig struct s s = { __lint_false };
734 1.13 rillig
735 1.19 rillig (void)((s.flag = s.flag) != __lint_false); /* expect: 129 */
736 1.13 rillig }
737 1.18 rillig
738 1.18 rillig void
739 1.18 rillig bool_as_array_index(bool cond)
740 1.18 rillig {
741 1.18 rillig static const char *repr[] = { "no", "yes" };
742 1.18 rillig /*
743 1.18 rillig * The '+' in the error message reveals that lint internally
744 1.18 rillig * translates 'arr[ind]' to '*(arr + ind)' in an early stage of
745 1.18 rillig * parsing.
746 1.18 rillig */
747 1.18 rillig println(repr[cond]); /* expect: 337 */
748 1.18 rillig println(cond ? "yes" : "no");
749 1.18 rillig }
750 1.20 rillig
751 1.20 rillig void
752 1.20 rillig do_while_false(void)
753 1.20 rillig {
754 1.20 rillig do {
755 1.20 rillig
756 1.21 rillig } while (__lint_false);
757 1.20 rillig }
758 1.20 rillig
759 1.20 rillig void
760 1.20 rillig do_while_true(void)
761 1.20 rillig {
762 1.20 rillig do {
763 1.20 rillig
764 1.20 rillig } while (__lint_true); /* expect: 161 */
765 1.20 rillig }
766 1.23 rillig
767 1.23 rillig void
768 1.23 rillig initialization(void)
769 1.23 rillig {
770 1.23 rillig struct {
771 1.23 rillig _Bool b;
772 1.23 rillig } var[] = {
773 1.23 rillig { __lint_false },
774 1.23 rillig { __lint_true },
775 1.24 rillig { 0 }, /* expect: 107 */
776 1.24 rillig { 1 }, /* expect: 107 */
777 1.23 rillig };
778 1.23 rillig }
779 1.31 rillig
780 1.31 rillig # 1 "stdio.h" 1 3 4
781 1.31 rillig typedef struct stdio_file {
782 1.31 rillig int fd;
783 1.31 rillig } FILE;
784 1.31 rillig int ferror(FILE *);
785 1.31 rillig FILE stdio_files[3];
786 1.31 rillig FILE *stdio_stdout;
787 1.31 rillig # 788 "d_c99_bool_strict.c" 2
788 1.31 rillig # 1 "string.h" 1 3 4
789 1.31 rillig int strcmp(const char *, const char *);
790 1.31 rillig # 791 "d_c99_bool_strict.c" 2
791 1.31 rillig
792 1.31 rillig void
793 1.31 rillig controlling_expression(FILE *f, const char *a, const char *b)
794 1.31 rillig {
795 1.31 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
796 1.31 rillig if (ferror(f))
797 1.31 rillig return;
798 1.31 rillig /* expect+1: error: controlling expression must be bool, not 'int' [333] */
799 1.31 rillig if (strcmp(a, b))
800 1.31 rillig return;
801 1.31 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
802 1.31 rillig if (!ferror(f))
803 1.31 rillig return;
804 1.31 rillig /* expect+1: error: operand of '!' must be bool, not 'int' [330] */
805 1.31 rillig if (!strcmp(a, b))
806 1.31 rillig return;
807 1.31 rillig
808 1.31 rillig /*
809 1.31 rillig * No warning below since the expression 'stdio_stdin' comes from a
810 1.31 rillig * system header (typically via a macro), and this property is passed
811 1.31 rillig * up to the expression 'ferror(stdio_stdin)'.
812 1.31 rillig *
813 1.31 rillig * That is wrong though since the above rule would allow a plain
814 1.31 rillig * 'strcmp' without a following '== 0', as long as one of its
815 1.31 rillig * arguments comes from a system header.
816 1.31 rillig *
817 1.31 rillig * Seen in bin/echo/echo.c, function main, call to ferror.
818 1.31 rillig */
819 1.31 rillig /* TODO: Warn about type mismatch [333]. */
820 1.31 rillig if (ferror(
821 1.31 rillig # 822 "d_c99_bool_strict.c" 3 4
822 1.31 rillig &stdio_files[1]
823 1.31 rillig # 824 "d_c99_bool_strict.c"
824 1.31 rillig ))
825 1.31 rillig return;
826 1.31 rillig
827 1.31 rillig /*
828 1.31 rillig * TODO: Why is there a difference between array access and a plain
829 1.31 rillig * variable? Either both should get a warning or none of them.
830 1.31 rillig */
831 1.31 rillig /* expect+5: error: controlling expression must be bool, not 'int' [333] */
832 1.31 rillig if (ferror(
833 1.31 rillig # 834 "d_c99_bool_strict.c" 3 4
834 1.31 rillig stdio_stdout
835 1.31 rillig # 836 "d_c99_bool_strict.c"
836 1.31 rillig ))
837 1.31 rillig return;
838 1.31 rillig }
839