d_c99_bool_strict.c revision 1.13 1 1.13 rillig /* $NetBSD: d_c99_bool_strict.c,v 1.13 2021/01/17 11:32:06 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.8 rillig * ! yes no
35 1.8 rillig * The other binary operators do not accept bool operands.
36 1.8 rillig *
37 1.8 rillig * strict-bool-operand-binary:
38 1.8 rillig * Operator left: bool? other? right: bool? other?
39 1.8 rillig * . - yes yes yes
40 1.8 rillig * -> - yes yes yes
41 1.11 rillig * <=, <, >=, > - yes - yes
42 1.8 rillig * ==, != yes yes 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 -
47 1.8 rillig * || yes - yes -
48 1.8 rillig * ? yes - yes yes
49 1.8 rillig * : yes 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 * The other binary operators do not accept bool operands.
54 1.8 rillig *
55 1.8 rillig * strict-bool-operator-result:
56 1.8 rillig * The result type of the operators '!', '<', '<=', '>', '>=',
57 1.8 rillig * '==', '!=', '&&', '||' is _Bool instead of int.
58 1.8 rillig *
59 1.8 rillig * strict-bool-bitwise-and:
60 1.8 rillig * Expressions of the form "flags & FLAG" are compatible with _Bool if
61 1.8 rillig * the left operand has enum type, the right operand is an integer
62 1.8 rillig * constant and the resulting value is used in a context where it is
63 1.8 rillig * implicitly and immediately compared to zero.
64 1.8 rillig *
65 1.8 rillig * Note: An efficient implementation technique for a collection of bool
66 1.8 rillig * flags is an enum. The enum declaration groups the available
67 1.8 rillig * constants, and as of 2020, compilers such as GCC and Clang have basic
68 1.8 rillig * support for detecting type mismatches on enums.
69 1.8 rillig *
70 1.8 rillig * Note: Examples for such contexts are controlling expressions or the
71 1.8 rillig * operands of the operators '!', '&&', '||'.
72 1.8 rillig *
73 1.8 rillig * Note: Counterexamples for contexts are assignments to a bool variable.
74 1.8 rillig *
75 1.8 rillig * Note: These rules ensure that conforming code can be compiled without
76 1.8 rillig * change in behavior using old compilers that implement bool as an
77 1.8 rillig * ordinary integer type, without the special rule C99 6.3.1.2.
78 1.8 rillig *
79 1.8 rillig * Note: There is a crucial difference between a _Bool variable and an
80 1.8 rillig * ordinary integer variable. C99 6.3.1.2 defines a conversion from an
81 1.8 rillig * arbitrary scalar value to _Bool as equivalent to (value != 0 ? 1 : 0).
82 1.8 rillig * This means that even if _Bool is implemented as an 8-bit unsigned
83 1.8 rillig * integer, assigning 256 to it would still result in the value 1 being
84 1.8 rillig * stored. Storing 256 in an ordinary 8-bit unsigned integer would
85 1.8 rillig * result in the value 0 being stored. See the test d_c99_bool.c for
86 1.8 rillig * more details.
87 1.8 rillig */
88 1.8 rillig
89 1.8 rillig /*
90 1.8 rillig * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and
91 1.8 rillig * true = 1. Without further hacks, this would mean that constant expressions
92 1.8 rillig * of integer type have to be regarded as possible boolean constants if their
93 1.8 rillig * value is either 0 or 1.
94 1.8 rillig *
95 1.8 rillig * This would not help in migrating old code to use bool consistently.
96 1.8 rillig * Therefore lint provides its own <stdbool.h> header that expands false to
97 1.8 rillig * __lint_false and true to __lint_true, two predefined constant expressions.
98 1.1 rillig */
99 1.1 rillig
100 1.4 rillig /* lint1-extra-flags: -T */
101 1.1 rillig
102 1.1 rillig /*
103 1.8 rillig * strict-bool-typedef
104 1.1 rillig */
105 1.1 rillig
106 1.1 rillig /*
107 1.1 rillig * Using a typedef for bool does not hurt the checks, they all use the
108 1.1 rillig * underlying basic type (see tspec_t), which is BOOL.
109 1.1 rillig */
110 1.1 rillig typedef _Bool bool;
111 1.1 rillig
112 1.8 rillig extern void accept_bool(bool);
113 1.8 rillig extern void println(const char *);
114 1.8 rillig extern void take_arguments(bool, int, const char *, ...);
115 1.8 rillig extern void do_nothing(void);
116 1.8 rillig
117 1.8 rillig /*
118 1.8 rillig * strict-bool-constant
119 1.8 rillig */
120 1.8 rillig
121 1.8 rillig void
122 1.8 rillig strict_bool_constant(void)
123 1.8 rillig {
124 1.8 rillig accept_bool(__lint_false);
125 1.8 rillig accept_bool(__lint_true);
126 1.9 rillig accept_bool(0); /* expect: 334 */
127 1.9 rillig accept_bool(1); /* expect: 334 */
128 1.8 rillig accept_bool(2); /* expect: 334 */
129 1.8 rillig }
130 1.8 rillig
131 1.8 rillig enum strict_bool_constant_expressions {
132 1.8 rillig /* Ok: __lint_false is a boolean constant expression. */
133 1.8 rillig FALSE = __lint_false ? 100 : 101,
134 1.8 rillig
135 1.8 rillig /* Ok: __lint_true is a boolean constant expression. */
136 1.8 rillig TRUE = __lint_true ? 100 : 101,
137 1.8 rillig
138 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
139 1.9 rillig INT0 = 0 ? 100 : 101, /* expect: 331 */
140 1.8 rillig
141 1.8 rillig /* Not ok: an integer is not a boolean constant expression. */
142 1.9 rillig INT1 = 1 ? 100 : 101, /* expect: 331 */
143 1.8 rillig
144 1.8 rillig /* Not ok: 2 is not a boolean constant. */
145 1.8 rillig INT2 = 2 ? 100 : 101, /* expect: 331 */
146 1.8 rillig
147 1.8 rillig /* Not ok: compound integer expressions are not bool. */
148 1.9 rillig ARITH = (2 - 2) ? 100 : 101, /* expect: 331 */
149 1.8 rillig
150 1.8 rillig /*
151 1.8 rillig * Without strict bool mode, these two variants of an expression can
152 1.8 rillig * occur when a preprocessor macro is either defined to 1 or left
153 1.8 rillig * empty, as in lint1/ops.def.
154 1.8 rillig *
155 1.8 rillig * TODO: figure out an elegant way to achieve the same effect in
156 1.8 rillig * strict bool mode.
157 1.8 rillig */
158 1.9 rillig BINARY_PLUS = (1 + 0) ? 100 : 101, /* expect: 331 */
159 1.9 rillig UNARY_PLUS = (+0) ? 100 : 101, /* expect: 331 */
160 1.8 rillig
161 1.8 rillig /* The main operator '>' has return type bool. */
162 1.8 rillig Q1 = (13 > 12) ? 100 : 101,
163 1.8 rillig
164 1.8 rillig /*
165 1.8 rillig * The parenthesized expression has type int and thus cannot be
166 1.8 rillig * used as the controlling expression in the '?:' operator.
167 1.8 rillig */
168 1.9 rillig Q2 = (13 > 12 ? 1 : 7) ? 100 : 101, /* expect: 331 */
169 1.8 rillig
170 1.8 rillig BINAND_BOOL = __lint_false & __lint_true,
171 1.8 rillig BINAND_INT = 0 & 1,
172 1.8 rillig
173 1.8 rillig BINXOR_BOOL = __lint_false ^ __lint_true,
174 1.8 rillig BINXOR_INT = 0 ^ 1,
175 1.8 rillig
176 1.8 rillig BINOR_BOOL = __lint_false | __lint_true,
177 1.8 rillig BINOR_INT = 0 | 1,
178 1.8 rillig
179 1.8 rillig LOGOR_BOOL = __lint_false || __lint_true,
180 1.9 rillig LOGOR_INT = 0 || 1, /* expect: 331, 332 */
181 1.8 rillig
182 1.8 rillig LOGAND_BOOL = __lint_false && __lint_true,
183 1.9 rillig LOGAND_INT = 0 && 1, /* expect: 331, 332 */
184 1.8 rillig };
185 1.8 rillig
186 1.8 rillig /*
187 1.8 rillig * strict-bool-bit-fields
188 1.8 rillig */
189 1.8 rillig
190 1.8 rillig void
191 1.8 rillig strict_bool_bit_fields(void)
192 1.8 rillig {
193 1.8 rillig struct flags {
194 1.8 rillig bool bool_flag: 1;
195 1.8 rillig unsigned uint_flag: 1;
196 1.8 rillig };
197 1.8 rillig
198 1.8 rillig struct flags flags = { __lint_false, 0 };
199 1.8 rillig struct flags *flags_ptr = &flags;
200 1.8 rillig bool b;
201 1.8 rillig
202 1.8 rillig b = flags.bool_flag;
203 1.8 rillig b = flags.uint_flag; /* expect: 107 */
204 1.8 rillig flags.bool_flag = b;
205 1.8 rillig flags.uint_flag = b; /* expect: 107 */
206 1.8 rillig
207 1.8 rillig b = flags_ptr->bool_flag;
208 1.8 rillig b = flags_ptr->uint_flag; /* expect: 107 */
209 1.8 rillig flags_ptr->bool_flag = b;
210 1.8 rillig flags_ptr->uint_flag = b; /* expect: 107 */
211 1.8 rillig }
212 1.8 rillig
213 1.8 rillig void
214 1.8 rillig strict_bool_bit_fields_operand_conversion(void)
215 1.8 rillig {
216 1.8 rillig struct s {
217 1.8 rillig bool ordinary;
218 1.8 rillig bool bit_field: 1;
219 1.8 rillig };
220 1.8 rillig
221 1.8 rillig struct s s = { 0 };
222 1.8 rillig
223 1.8 rillig s.ordinary = s.ordinary | s.ordinary;
224 1.8 rillig s.bit_field = s.bit_field | s.bit_field; /* FIXME *//* expect: 107 */
225 1.8 rillig }
226 1.8 rillig
227 1.8 rillig /*
228 1.8 rillig * strict-bool-conversion
229 1.8 rillig */
230 1.8 rillig
231 1.8 rillig bool
232 1.8 rillig strict_bool_conversion_return_false(void)
233 1.8 rillig {
234 1.8 rillig return __lint_false;
235 1.8 rillig }
236 1.8 rillig
237 1.8 rillig bool
238 1.8 rillig strict_bool_conversion_return_true(void)
239 1.8 rillig {
240 1.8 rillig return __lint_true;
241 1.8 rillig }
242 1.8 rillig
243 1.8 rillig bool
244 1.8 rillig strict_bool_conversion_return_bool(bool b)
245 1.8 rillig {
246 1.8 rillig return b;
247 1.8 rillig }
248 1.8 rillig
249 1.8 rillig bool
250 1.8 rillig strict_bool_conversion_return_0(void)
251 1.8 rillig {
252 1.9 rillig return 0; /* expect: 211 */
253 1.8 rillig }
254 1.8 rillig
255 1.8 rillig bool
256 1.8 rillig strict_bool_conversion_return_1(void)
257 1.8 rillig {
258 1.9 rillig return 1; /* expect: 211 */
259 1.8 rillig }
260 1.8 rillig
261 1.8 rillig bool
262 1.8 rillig strict_bool_conversion_return_2(void)
263 1.8 rillig {
264 1.8 rillig return 2; /* expect: 211 */
265 1.8 rillig }
266 1.8 rillig
267 1.8 rillig bool
268 1.8 rillig strict_bool_conversion_return_pointer(const void *p) /* expect: 231 */
269 1.8 rillig {
270 1.8 rillig return p; /* expect: 211 */
271 1.8 rillig }
272 1.8 rillig
273 1.8 rillig char
274 1.8 rillig strict_bool_conversion_return_false_as_char(void)
275 1.8 rillig {
276 1.8 rillig return __lint_false; /* expect: 211 */
277 1.8 rillig }
278 1.8 rillig
279 1.8 rillig char
280 1.8 rillig strict_bool_conversion_return_true_as_char(void)
281 1.8 rillig {
282 1.8 rillig return __lint_true; /* expect: 211 */
283 1.8 rillig }
284 1.8 rillig
285 1.8 rillig
286 1.1 rillig void
287 1.8 rillig strict_bool_conversion_function_argument(void)
288 1.1 rillig {
289 1.8 rillig accept_bool(__lint_false);
290 1.8 rillig accept_bool(__lint_true);
291 1.8 rillig }
292 1.8 rillig
293 1.8 rillig void
294 1.8 rillig strict_bool_conversion_function_argument_pass(bool b, int i, const char *p)
295 1.8 rillig {
296 1.8 rillig /* No conversion necessary. */
297 1.8 rillig take_arguments(b, i, p);
298 1.8 rillig
299 1.8 rillig /* Implicitly converting bool to other scalar types. */
300 1.8 rillig take_arguments(b, b, b); /* expect: 334, 334 */
301 1.8 rillig
302 1.8 rillig /* Implicitly converting int to bool (arg #1). */
303 1.8 rillig take_arguments(i, i, i); /* expect: 334, 154 */
304 1.8 rillig
305 1.8 rillig /* Implicitly converting pointer to bool (arg #1). */
306 1.8 rillig take_arguments(p, p, p); /* expect: 334, 154 */
307 1.8 rillig
308 1.8 rillig /* Passing bool as vararg. */
309 1.8 rillig take_arguments(b, i, p, b, i, p); /* expect: arg#4 */ // TODO
310 1.8 rillig
311 1.8 rillig /* Passing a bool constant. */
312 1.8 rillig take_arguments(__lint_false, i, p);
313 1.8 rillig
314 1.8 rillig /* Passing a bool constant. */
315 1.8 rillig take_arguments(__lint_true, i, p);
316 1.8 rillig
317 1.8 rillig /* Trying to pass integer constants. */
318 1.9 rillig take_arguments(0, i, p); /* expect: 334 */
319 1.9 rillig take_arguments(1, i, p); /* expect: 334 */
320 1.8 rillig take_arguments(2, i, p); /* expect: 334 */
321 1.8 rillig }
322 1.1 rillig
323 1.8 rillig void
324 1.8 rillig strict_bool_conversion_between_bool_and_int(void)
325 1.8 rillig {
326 1.8 rillig bool b;
327 1.8 rillig int i;
328 1.1 rillig
329 1.9 rillig b = 0; /* expect: 107 */
330 1.9 rillig b = __lint_false;
331 1.9 rillig b = 1; /* expect: 107 */
332 1.8 rillig b = __lint_true;
333 1.1 rillig
334 1.8 rillig i = 0;
335 1.8 rillig i = __lint_false; /* expect: 107 */
336 1.8 rillig i = 1;
337 1.8 rillig i = __lint_true; /* expect: 107 */
338 1.8 rillig
339 1.8 rillig i = b; /* expect: 107 */
340 1.8 rillig b = i; /* expect: 107 */
341 1.8 rillig }
342 1.8 rillig
343 1.8 rillig void
344 1.8 rillig strict_bool_conversion_from_bool_to_scalar(bool b) /* expect: 231 */
345 1.8 rillig {
346 1.8 rillig int i;
347 1.8 rillig unsigned u;
348 1.8 rillig double d;
349 1.8 rillig void *p;
350 1.8 rillig
351 1.8 rillig i = b; /* expect: 107 */
352 1.8 rillig u = b; /* expect: 107 */
353 1.8 rillig d = b; /* expect: 107 */
354 1.8 rillig p = b; /* expect: 107 */
355 1.8 rillig }
356 1.8 rillig
357 1.8 rillig /*
358 1.8 rillig * strict-bool-controlling-expression:
359 1.8 rillig * Controlling expressions in 'if', 'while', 'for', '?:' must be of
360 1.8 rillig * type bool.
361 1.8 rillig */
362 1.8 rillig
363 1.8 rillig void
364 1.8 rillig strict_bool_controlling_expression(bool b, int i, double d, const void *p)
365 1.8 rillig {
366 1.8 rillig if (__lint_false)
367 1.8 rillig do_nothing();
368 1.8 rillig
369 1.8 rillig if (__lint_true)
370 1.8 rillig do_nothing();
371 1.8 rillig
372 1.8 rillig if (b)
373 1.8 rillig do_nothing();
374 1.8 rillig
375 1.9 rillig if (0) /* expect: 333 */
376 1.8 rillig do_nothing();
377 1.8 rillig
378 1.9 rillig if (1) /* expect: 333 */
379 1.8 rillig do_nothing();
380 1.8 rillig
381 1.8 rillig if (2) /* expect: 333 */
382 1.8 rillig do_nothing();
383 1.1 rillig
384 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
385 1.4 rillig if (i) /* expect: 333 */
386 1.8 rillig do_nothing();
387 1.1 rillig if (i != 0)
388 1.8 rillig do_nothing();
389 1.1 rillig
390 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
391 1.4 rillig if (d) /* expect: 333 */
392 1.8 rillig do_nothing();
393 1.1 rillig if (d != 0.0)
394 1.8 rillig do_nothing();
395 1.1 rillig
396 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
397 1.4 rillig if (p) /* expect: 333 */
398 1.8 rillig do_nothing();
399 1.1 rillig if (p != (void *)0)
400 1.8 rillig do_nothing();
401 1.8 rillig }
402 1.1 rillig
403 1.8 rillig /*
404 1.8 rillig * strict-bool-operand-unary:
405 1.8 rillig * Operator bool? scalar?
406 1.8 rillig * ! yes -
407 1.8 rillig * & yes yes
408 1.8 rillig * The other binary operators do not accept bool operands.
409 1.8 rillig */
410 1.8 rillig
411 1.8 rillig void
412 1.8 rillig strict_bool_operand_unary_not(void)
413 1.8 rillig {
414 1.8 rillig bool b = __lint_false;
415 1.8 rillig
416 1.8 rillig b = !b;
417 1.8 rillig b = !!!b;
418 1.8 rillig b = !__lint_false;
419 1.8 rillig b = !__lint_true;
420 1.8 rillig
421 1.8 rillig int i = 0;
422 1.8 rillig
423 1.8 rillig i = !i; /* expect: 330 */
424 1.8 rillig i = !!!i; /* expect: 330 */
425 1.9 rillig i = !0; /* expect: 330 */
426 1.9 rillig i = !1; /* expect: 330 */
427 1.8 rillig }
428 1.8 rillig
429 1.8 rillig void
430 1.8 rillig strict_bool_operand_unary_address(void)
431 1.8 rillig {
432 1.8 rillig bool b = __lint_false;
433 1.8 rillig
434 1.8 rillig /* Taking the address of a bool lvalue. */
435 1.8 rillig bool *bp;
436 1.8 rillig bp = &b;
437 1.8 rillig *bp = b;
438 1.8 rillig b = *bp;
439 1.1 rillig }
440 1.1 rillig
441 1.8 rillig /*
442 1.8 rillig * strict-bool-operand-binary:
443 1.8 rillig * Operator left: bool? other? right: bool? other?
444 1.8 rillig * . - yes yes yes
445 1.8 rillig * -> - yes yes yes
446 1.11 rillig * <=, <, >=, > - yes - yes
447 1.8 rillig * ==, != yes yes yes yes
448 1.8 rillig * & yes yes yes yes
449 1.8 rillig * ^ yes yes yes yes
450 1.8 rillig * | yes yes yes yes
451 1.8 rillig * && yes - yes -
452 1.8 rillig * || yes - yes -
453 1.8 rillig * ? yes - yes yes
454 1.8 rillig * : yes yes yes yes
455 1.8 rillig * = yes yes yes yes
456 1.8 rillig * &=, ^=, |= yes yes yes yes
457 1.8 rillig * , yes yes yes yes
458 1.8 rillig * The other binary operators do not accept bool operands.
459 1.8 rillig */
460 1.8 rillig
461 1.8 rillig /*
462 1.8 rillig * Ensure that bool members can be accessed as usual.
463 1.8 rillig */
464 1.1 rillig void
465 1.8 rillig strict_bool_operand_binary_dot_arrow(void)
466 1.1 rillig {
467 1.8 rillig struct bool_struct {
468 1.8 rillig bool b;
469 1.8 rillig };
470 1.8 rillig
471 1.8 rillig /* Initialize and assign using boolean constants. */
472 1.8 rillig bool b = __lint_false;
473 1.8 rillig b = __lint_true;
474 1.1 rillig
475 1.8 rillig /* Access a struct member using the '.' operator. */
476 1.8 rillig struct bool_struct bs = { __lint_true };
477 1.8 rillig b = bs.b;
478 1.8 rillig bs.b = b;
479 1.9 rillig bs.b = 0; /* expect: 107 */
480 1.1 rillig
481 1.8 rillig /* Access a struct member using the '->' operator. */
482 1.8 rillig struct bool_struct *bsp = &bs;
483 1.8 rillig b = bsp->b;
484 1.8 rillig bsp->b = b;
485 1.9 rillig bsp->b = 0; /* expect: 107 */
486 1.1 rillig }
487 1.1 rillig
488 1.4 rillig int
489 1.8 rillig strict_bool_operand_binary(bool b, int i)
490 1.1 rillig {
491 1.1 rillig
492 1.4 rillig /* The right-hand sides of these assignments are ok. */
493 1.1 rillig b = !b;
494 1.1 rillig b = b && b;
495 1.1 rillig b = b || b;
496 1.1 rillig
497 1.4 rillig /*
498 1.4 rillig * The right-hand sides of these assignments implicitly convert from
499 1.4 rillig * scalar to bool.
500 1.4 rillig */
501 1.4 rillig b = !i; /* expect: 330 */
502 1.4 rillig b = i && i; /* expect: 331, 332 */
503 1.4 rillig b = i || i; /* expect: 331, 332 */
504 1.4 rillig
505 1.9 rillig b = b && 0; /* expect: 332 */
506 1.9 rillig b = 0 && b; /* expect: 331 */
507 1.9 rillig b = b || 0; /* expect: 332 */
508 1.9 rillig b = 0 || b; /* expect: 331 */
509 1.4 rillig
510 1.4 rillig return i;
511 1.1 rillig }
512 1.1 rillig
513 1.1 rillig void
514 1.8 rillig strict_bool_operand_binary_all(bool b, unsigned u)
515 1.1 rillig {
516 1.8 rillig b = !b;
517 1.4 rillig b = ~b; /* expect: 335 */
518 1.4 rillig ++b; /* expect: 335 */
519 1.4 rillig --b; /* expect: 335 */
520 1.4 rillig b++; /* expect: 335 */
521 1.4 rillig b--; /* expect: 335 */
522 1.4 rillig b = +b; /* expect: 335 */
523 1.4 rillig b = -b; /* expect: 335 */
524 1.4 rillig
525 1.4 rillig b = b * b; /* expect: 336, 337 */
526 1.4 rillig b = b / b; /* expect: 336, 337 */
527 1.4 rillig b = b % b; /* expect: 336, 337 */
528 1.4 rillig b = b + b; /* expect: 336, 337 */
529 1.4 rillig b = b - b; /* expect: 336, 337 */
530 1.4 rillig b = b << b; /* expect: 336, 337 */
531 1.4 rillig b = b >> b; /* expect: 336, 337 */
532 1.4 rillig
533 1.4 rillig b = b < b; /* expect: 336, 337 */
534 1.4 rillig b = b <= b; /* expect: 336, 337 */
535 1.4 rillig b = b > b; /* expect: 336, 337 */
536 1.4 rillig b = b >= b; /* expect: 336, 337 */
537 1.8 rillig b = b == b;
538 1.8 rillig b = b != b;
539 1.1 rillig
540 1.8 rillig b = b & b;
541 1.8 rillig b = b ^ b;
542 1.8 rillig b = b | b;
543 1.8 rillig b = b && b;
544 1.8 rillig b = b || b;
545 1.8 rillig b = b ? b : b;
546 1.1 rillig
547 1.8 rillig b = b;
548 1.4 rillig b *= b; /* expect: 336, 337 */
549 1.4 rillig b /= b; /* expect: 336, 337 */
550 1.4 rillig b %= b; /* expect: 336, 337 */
551 1.4 rillig b += b; /* expect: 336, 337 */
552 1.4 rillig b -= b; /* expect: 336, 337 */
553 1.4 rillig b <<= b; /* expect: 336, 337 */
554 1.4 rillig b >>= b; /* expect: 336, 337 */
555 1.8 rillig b &= b;
556 1.8 rillig b ^= b;
557 1.8 rillig b |= b;
558 1.1 rillig
559 1.1 rillig /* Operations with mixed types. */
560 1.4 rillig u = b * u; /* expect: 336 */
561 1.4 rillig u = u * b; /* expect: 337 */
562 1.4 rillig u = b / u; /* expect: 336 */
563 1.4 rillig u = u / b; /* expect: 337 */
564 1.4 rillig u = b % u; /* expect: 336 */
565 1.4 rillig u = u % b; /* expect: 337 */
566 1.4 rillig u = b + u; /* expect: 336 */
567 1.4 rillig u = u + b; /* expect: 337 */
568 1.4 rillig u = b - u; /* expect: 336 */
569 1.4 rillig u = u - b; /* expect: 337 */
570 1.4 rillig u = b << u; /* expect: 336 */
571 1.4 rillig u = u << b; /* expect: 337 */
572 1.4 rillig u = b >> u; /* expect: 336 */
573 1.4 rillig u = u >> b; /* expect: 337 */
574 1.8 rillig u = b ? u : u;
575 1.4 rillig u = b ? b : u; /* expect: 107 */
576 1.4 rillig u = b ? u : b; /* expect: 107 */
577 1.1 rillig }
578 1.1 rillig
579 1.8 rillig bool
580 1.8 rillig strict_bool_operand_binary_comma(bool b, int i)
581 1.1 rillig {
582 1.8 rillig b = (b, !b);
583 1.8 rillig i = (i, i + 1);
584 1.8 rillig return b;
585 1.1 rillig }
586 1.1 rillig
587 1.8 rillig /*
588 1.8 rillig * strict-bool-operator-result:
589 1.8 rillig * The result type of the operators '!', '<', '<=', '>', '>=',
590 1.8 rillig * '==', '!=', '&&', '||' is _Bool instead of int.
591 1.8 rillig */
592 1.1 rillig
593 1.8 rillig void
594 1.8 rillig strict_bool_operator_result(bool b)
595 1.8 rillig {
596 1.8 rillig char c = b; /* expect: 107 */
597 1.8 rillig int i = b; /* expect: 107 */
598 1.8 rillig double d = b; /* expect: 107 */
599 1.8 rillig void *p = b; /* expect: 107 */
600 1.1 rillig
601 1.8 rillig /* The right-hand sides of these assignments are all ok. */
602 1.8 rillig b = !b;
603 1.8 rillig b = i == i;
604 1.8 rillig b = i != i;
605 1.8 rillig b = i < i;
606 1.8 rillig b = i <= i;
607 1.8 rillig b = i >= i;
608 1.8 rillig b = i > i;
609 1.8 rillig b = b && b;
610 1.8 rillig b = b || b;
611 1.1 rillig
612 1.1 rillig /*
613 1.8 rillig * The right-hand sides of these assignments are not ok, they
614 1.8 rillig * implicitly convert from bool to int.
615 1.1 rillig */
616 1.8 rillig i = !b; /* expect: 107 */
617 1.8 rillig i = i == i; /* expect: 107 */
618 1.8 rillig i = i != i; /* expect: 107 */
619 1.8 rillig i = i < i; /* expect: 107 */
620 1.8 rillig i = i <= i; /* expect: 107 */
621 1.8 rillig i = i >= i; /* expect: 107 */
622 1.8 rillig i = i > i; /* expect: 107 */
623 1.8 rillig i = b && b; /* expect: 107 */
624 1.8 rillig i = b || b; /* expect: 107 */
625 1.8 rillig }
626 1.1 rillig
627 1.2 rillig
628 1.3 rillig /*
629 1.8 rillig * strict-bool-bitwise-and:
630 1.8 rillig * Expressions of the form "flags & FLAG" are compatible with _Bool if
631 1.8 rillig * the left operand has enum type, the right operand is an integer
632 1.8 rillig * constant and the resulting value is used in a context where it is
633 1.8 rillig * implicitly and immediately compared to zero.
634 1.8 rillig *
635 1.8 rillig * Note: Examples for such contexts are controlling expressions or the
636 1.8 rillig * operands of the operators '!', '&&', '||'.
637 1.8 rillig *
638 1.8 rillig * Note: Counterexamples for contexts are assignments to a bool variable.
639 1.8 rillig *
640 1.8 rillig * Note: These rules ensure that conforming code can be compiled without
641 1.8 rillig * change in behavior using old compilers that implement bool as an
642 1.8 rillig * ordinary integer type, without the special rule C99 6.3.1.2.
643 1.3 rillig */
644 1.3 rillig
645 1.3 rillig enum Flags {
646 1.3 rillig FLAG0 = 1 << 0,
647 1.3 rillig FLAG1 = 1 << 1,
648 1.3 rillig FLAG28 = 1 << 28
649 1.2 rillig };
650 1.2 rillig
651 1.3 rillig void
652 1.8 rillig strict_bool_bitwise_and_enum(enum Flags flags) /* expect: 231 */
653 1.3 rillig {
654 1.3 rillig bool b;
655 1.3 rillig
656 1.3 rillig /*
657 1.4 rillig * FLAG0 has the value 1 and thus can be stored in a bool variable
658 1.4 rillig * without truncation. Nevertheless this special case is not allowed
659 1.4 rillig * because it would be too confusing if FLAG0 would work and all the
660 1.4 rillig * other flags wouldn't.
661 1.3 rillig */
662 1.4 rillig b = flags & FLAG0; /* expect: 107 */
663 1.3 rillig
664 1.3 rillig /*
665 1.3 rillig * Assuming that FLAG1 is set in flags, a _Bool variable stores this
666 1.4 rillig * as 1, as defined by C99 6.3.1.2. A uint8_t variable would store
667 1.4 rillig * it as 2, as that is the integer value of FLAG1. Since FLAG1 fits
668 1.4 rillig * in a uint8_t, no truncation takes place.
669 1.3 rillig */
670 1.4 rillig b = flags & FLAG1; /* expect: 107 */
671 1.3 rillig
672 1.3 rillig /*
673 1.4 rillig * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
674 1.4 rillig * zero. In a uint8_t, the stored value would be 0 since bit 28 is
675 1.4 rillig * out of range for a uint8_t and thus gets truncated.
676 1.3 rillig */
677 1.4 rillig b = flags & FLAG28; /* expect: 107 */
678 1.3 rillig }
679 1.3 rillig
680 1.4 rillig /*
681 1.8 rillig * Demonstrate idiomatic code to query flags from an enum bit set.
682 1.8 rillig *
683 1.8 rillig * In all the controlling expressions in this function, the result of the
684 1.8 rillig * operator '&' is compared against 0. This makes this pattern work, no
685 1.8 rillig * matter whether the bits are in the low-value range or in the high-value
686 1.8 rillig * range (such as FLAG28, which has the value 1073741824, which is more than
687 1.8 rillig * what would fit into an unsigned char). Even if an enum could be extended
688 1.8 rillig * to larger types than int, this pattern would work.
689 1.4 rillig */
690 1.4 rillig void
691 1.8 rillig query_flag_from_enum_bit_set(enum Flags flags)
692 1.4 rillig {
693 1.8 rillig if (flags & FLAG0)
694 1.8 rillig println("FLAG0 is set");
695 1.4 rillig
696 1.8 rillig if ((flags & FLAG1) != 0)
697 1.8 rillig println("FLAG1 is set");
698 1.4 rillig
699 1.8 rillig if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
700 1.8 rillig println("FLAG0 and FLAG1 are both set");
701 1.4 rillig
702 1.8 rillig if (flags & FLAG0 && flags & FLAG1)
703 1.8 rillig println("FLAG0 and FLAG1 are both set");
704 1.4 rillig
705 1.8 rillig if ((flags & (FLAG0 | FLAG1)) != 0)
706 1.8 rillig println("At least one of FLAG0 and FLAG1 is set");
707 1.4 rillig
708 1.8 rillig if (flags & FLAG28)
709 1.8 rillig println("FLAG28 is set");
710 1.7 rillig }
711 1.10 rillig
712 1.10 rillig
713 1.12 rillig void
714 1.10 rillig strict_bool_operator_eq_bool_int(void)
715 1.10 rillig {
716 1.12 rillig (void)(strict_bool_conversion_return_false() == 0); /* expect: 107 */
717 1.10 rillig }
718 1.13 rillig
719 1.13 rillig void
720 1.13 rillig strict_bool_assign_bit_field_then_compare(void)
721 1.13 rillig {
722 1.13 rillig struct s {
723 1.13 rillig bool flag: 1;
724 1.13 rillig };
725 1.13 rillig
726 1.13 rillig struct s s = { __lint_false };
727 1.13 rillig
728 1.13 rillig /* FIXME: The __lint_false is converted irreversibly to an INT. */
729 1.13 rillig (void)((s.flag = s.flag) != __lint_false); /* expect: 107 */
730 1.13 rillig }
731