d_c99_bool_strict.c revision 1.4 1 1.4 rillig /* $NetBSD: d_c99_bool_strict.c,v 1.4 2021/01/12 20:42:01 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.4 rillig * This means:
7 1.1 rillig *
8 1.1 rillig * SB001: Controlling expressions in 'if', 'while', 'for', '?:' must be of
9 1.1 rillig * type _Bool instead of scalar.
10 1.1 rillig *
11 1.1 rillig * SB002: The operators '!', '==', '!=', '<', '<=', '>=', '>', '&&', '||'
12 1.1 rillig * return _Bool instead of int.
13 1.1 rillig *
14 1.1 rillig * SB003: The operators '!', '&&', '||' take _Bool instead of scalar.
15 1.1 rillig *
16 1.1 rillig * SB004: The only operators that take _Bool are '!', '==', '!=',
17 1.1 rillig * '&', '^', '|', '&&', '||', '?', ':', '=', '&=', '^=', '|='.
18 1.1 rillig *
19 1.1 rillig * SB005: There is no implicit conversion from _Bool to any other type.
20 1.1 rillig *
21 1.4 rillig * SB006: An expression is compatible with type _Bool if its main operator
22 1.4 rillig * returns type _Bool, or if the expression is an integer constant expression
23 1.4 rillig * with value 0 or 1.
24 1.3 rillig *
25 1.3 rillig * SB007: Expressions like "flags & FLAG" are compatible with _Bool if
26 1.3 rillig * they appear in a context where they are immediately compared to zero.
27 1.3 rillig * Assigning to a _Bool variable does not count as such a context, to
28 1.3 rillig * allow programs to be compiled without silent changes on a compiler that
29 1.3 rillig * is lacking the special _Bool type.
30 1.3 rillig *
31 1.3 rillig * SB008: Bit fields in struct may be based on _Bool. These bit fields
32 1.3 rillig * typically have type _Bool:1 and can be converted to _Bool and back.
33 1.1 rillig */
34 1.1 rillig
35 1.4 rillig /* lint1-extra-flags: -T */
36 1.1 rillig
37 1.1 rillig /*
38 1.1 rillig * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and
39 1.1 rillig * true = 1. Therefore, constant expressions of integer type have to be
40 1.1 rillig * regarded as possible boolean constants if their value is either 0 or 1.
41 1.1 rillig * At this point of the translation, the preprocessor has already removed
42 1.1 rillig * the words "false" and "true" from the source code.
43 1.1 rillig */
44 1.1 rillig
45 1.1 rillig /*
46 1.1 rillig * Using a typedef for bool does not hurt the checks, they all use the
47 1.1 rillig * underlying basic type (see tspec_t), which is BOOL.
48 1.1 rillig */
49 1.1 rillig typedef _Bool bool;
50 1.1 rillig
51 1.1 rillig void
52 1.1 rillig SB001_controlling_expression(bool b, int i, double d, const void *p)
53 1.1 rillig {
54 1.1 rillig
55 1.1 rillig /* Fine due to SB006. */
56 1.1 rillig if (/*CONSTCOND*/0)
57 1.1 rillig return;
58 1.1 rillig
59 1.1 rillig /* Fine due to SB006. */
60 1.1 rillig if (/*CONSTCOND*/1)
61 1.1 rillig return;
62 1.1 rillig
63 1.1 rillig /* Not allowed: 2 is not a boolean expression. */
64 1.4 rillig if (/*CONSTCOND*/2) /* expect: 333 */
65 1.1 rillig return;
66 1.1 rillig
67 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
68 1.4 rillig if (i) /* expect: 333 */
69 1.1 rillig return;
70 1.1 rillig if (i != 0)
71 1.1 rillig return;
72 1.1 rillig
73 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
74 1.4 rillig if (d) /* expect: 333 */
75 1.1 rillig return;
76 1.1 rillig if (d != 0.0)
77 1.1 rillig return;
78 1.1 rillig
79 1.1 rillig /* Not allowed: There is no implicit conversion from scalar to bool. */
80 1.4 rillig if (p) /* expect: 333 */
81 1.1 rillig return;
82 1.1 rillig if (p != (void *)0)
83 1.1 rillig return;
84 1.1 rillig
85 1.1 rillig /* Using a bool expression is allowed. */
86 1.1 rillig if (b)
87 1.1 rillig return;
88 1.1 rillig }
89 1.1 rillig
90 1.1 rillig void
91 1.4 rillig SB002_operator_result_type(bool b)
92 1.1 rillig {
93 1.1 rillig b = b;
94 1.4 rillig char c = b; /* expect: 107 */
95 1.4 rillig int i = b; /* expect: 107 */
96 1.4 rillig double d = b; /* expect: 107 */
97 1.4 rillig void *p = b; /* expect: 107 */
98 1.1 rillig
99 1.4 rillig /* The right-hand sides of these assignments are all ok. */
100 1.1 rillig b = !b;
101 1.1 rillig b = i == i;
102 1.1 rillig b = i != i;
103 1.1 rillig b = i < i;
104 1.1 rillig b = i <= i;
105 1.1 rillig b = i >= i;
106 1.1 rillig b = i > i;
107 1.1 rillig b = b && b;
108 1.1 rillig b = b || b;
109 1.1 rillig
110 1.1 rillig /*
111 1.4 rillig * The right-hand sides of these assignments are not ok, they
112 1.4 rillig * implicitly convert from bool to int.
113 1.1 rillig */
114 1.4 rillig i = !b; /* expect: 107 */
115 1.4 rillig i = i == i; /* expect: 107 */
116 1.4 rillig i = i != i; /* expect: 107 */
117 1.4 rillig i = i < i; /* expect: 107 */
118 1.4 rillig i = i <= i; /* expect: 107 */
119 1.4 rillig i = i >= i; /* expect: 107 */
120 1.4 rillig i = i > i; /* expect: 107 */
121 1.4 rillig i = b && b; /* expect: 107 */
122 1.4 rillig i = b || b; /* expect: 107 */
123 1.1 rillig }
124 1.1 rillig
125 1.4 rillig int
126 1.1 rillig SB003_operands(bool b, int i)
127 1.1 rillig {
128 1.1 rillig
129 1.4 rillig /* The right-hand sides of these assignments are ok. */
130 1.1 rillig b = !b;
131 1.1 rillig b = b && b;
132 1.1 rillig b = b || b;
133 1.1 rillig
134 1.4 rillig /*
135 1.4 rillig * The right-hand sides of these assignments implicitly convert from
136 1.4 rillig * scalar to bool.
137 1.4 rillig */
138 1.4 rillig b = !i; /* expect: 330 */
139 1.4 rillig b = i && i; /* expect: 331, 332 */
140 1.4 rillig b = i || i; /* expect: 331, 332 */
141 1.4 rillig
142 1.4 rillig b = b && 0;
143 1.4 rillig b = 0 && b;
144 1.4 rillig b = b || 0;
145 1.4 rillig b = 0 || b;
146 1.4 rillig
147 1.4 rillig return i;
148 1.1 rillig }
149 1.1 rillig
150 1.4 rillig /*ARGSUSED*/
151 1.1 rillig void
152 1.4 rillig SB004_operators_and_bool_operands(bool b, unsigned u)
153 1.1 rillig {
154 1.1 rillig b = !b; /* ok */
155 1.4 rillig b = ~b; /* expect: 335 */
156 1.4 rillig ++b; /* expect: 335 */
157 1.4 rillig --b; /* expect: 335 */
158 1.4 rillig b++; /* expect: 335 */
159 1.4 rillig b--; /* expect: 335 */
160 1.4 rillig b = +b; /* expect: 335 */
161 1.4 rillig b = -b; /* expect: 335 */
162 1.4 rillig
163 1.4 rillig b = b * b; /* expect: 336, 337 */
164 1.4 rillig b = b / b; /* expect: 336, 337 */
165 1.4 rillig b = b % b; /* expect: 336, 337 */
166 1.4 rillig b = b + b; /* expect: 336, 337 */
167 1.4 rillig b = b - b; /* expect: 336, 337 */
168 1.4 rillig b = b << b; /* expect: 336, 337 */
169 1.4 rillig b = b >> b; /* expect: 336, 337 */
170 1.4 rillig
171 1.4 rillig b = b < b; /* expect: 336, 337 */
172 1.4 rillig b = b <= b; /* expect: 336, 337 */
173 1.4 rillig b = b > b; /* expect: 336, 337 */
174 1.4 rillig b = b >= b; /* expect: 336, 337 */
175 1.1 rillig b = b == b; /* ok */
176 1.1 rillig b = b != b; /* ok */
177 1.1 rillig
178 1.1 rillig b = b & b; /* ok */
179 1.1 rillig b = b ^ b; /* ok */
180 1.1 rillig b = b | b; /* ok */
181 1.1 rillig b = b && b; /* ok */
182 1.1 rillig b = b || b; /* ok */
183 1.1 rillig b = b ? b : b; /* ok */
184 1.1 rillig
185 1.1 rillig b = b; /* ok */
186 1.4 rillig b *= b; /* expect: 336, 337 */
187 1.4 rillig b /= b; /* expect: 336, 337 */
188 1.4 rillig b %= b; /* expect: 336, 337 */
189 1.4 rillig b += b; /* expect: 336, 337 */
190 1.4 rillig b -= b; /* expect: 336, 337 */
191 1.4 rillig b <<= b; /* expect: 336, 337 */
192 1.4 rillig b >>= b; /* expect: 336, 337 */
193 1.1 rillig b &= b; /* ok */
194 1.1 rillig b ^= b; /* ok */
195 1.1 rillig b |= b; /* ok */
196 1.1 rillig
197 1.1 rillig /* Operations with mixed types. */
198 1.4 rillig u = b * u; /* expect: 336 */
199 1.4 rillig u = u * b; /* expect: 337 */
200 1.4 rillig u = b / u; /* expect: 336 */
201 1.4 rillig u = u / b; /* expect: 337 */
202 1.4 rillig u = b % u; /* expect: 336 */
203 1.4 rillig u = u % b; /* expect: 337 */
204 1.4 rillig u = b + u; /* expect: 336 */
205 1.4 rillig u = u + b; /* expect: 337 */
206 1.4 rillig u = b - u; /* expect: 336 */
207 1.4 rillig u = u - b; /* expect: 337 */
208 1.4 rillig u = b << u; /* expect: 336 */
209 1.4 rillig u = u << b; /* expect: 337 */
210 1.4 rillig u = b >> u; /* expect: 336 */
211 1.4 rillig u = u >> b; /* expect: 337 */
212 1.1 rillig u = b ? u : u; /* ok */
213 1.4 rillig u = b ? b : u; /* expect: 107 */
214 1.4 rillig u = b ? u : b; /* expect: 107 */
215 1.1 rillig }
216 1.1 rillig
217 1.4 rillig /*ARGSUSED*/
218 1.1 rillig void
219 1.1 rillig SB005_convert_from_bool_to_scalar(bool b)
220 1.1 rillig {
221 1.1 rillig int i;
222 1.1 rillig unsigned u;
223 1.1 rillig double d;
224 1.1 rillig void *p;
225 1.1 rillig
226 1.4 rillig i = b; /* expect: 107 */
227 1.4 rillig u = b; /* expect: 107 */
228 1.4 rillig d = b; /* expect: 107 */
229 1.4 rillig p = b; /* expect: 107 */
230 1.1 rillig }
231 1.1 rillig
232 1.1 rillig enum SB006_bool_constant_expression {
233 1.1 rillig /* Ok: 0 is a boolean constant expression. */
234 1.1 rillig INT0 = 0 ? 100 : 101,
235 1.1 rillig
236 1.1 rillig /* Ok: 1 is a boolean constant expression. */
237 1.1 rillig INT1 = 1 ? 100 : 101,
238 1.1 rillig
239 1.1 rillig /* Not ok: 2 is not a boolean constant (neither 0 nor 1). */
240 1.4 rillig INT2 = 2 ? 100 : 101, /* expect: 331 */
241 1.1 rillig
242 1.1 rillig /*
243 1.4 rillig * The intermediate expression "2" has type int, which is not
244 1.4 rillig * compatible with _Bool. The expression "2 - 2" is an integer
245 1.4 rillig * constant expression with value 0 and is thus a bool constant
246 1.4 rillig * expression. This particular case probably does not occur in
247 1.4 rillig * practice.
248 1.1 rillig */
249 1.1 rillig ARITH = (2 - 2) ? 100 : 101,
250 1.1 rillig
251 1.1 rillig /*
252 1.4 rillig * These two variants of an expression can occur when a preprocessor
253 1.4 rillig * macro is either defined to 1 or left empty, as in lint1/ops.def.
254 1.1 rillig */
255 1.4 rillig BINARY_PLUS = (1 + 0) ? 100 : 101,
256 1.4 rillig UNARY_PLUS = (+0) ? 100 : 101,
257 1.4 rillig
258 1.4 rillig /* The main operator '>' has return type bool. */
259 1.1 rillig Q1 = (13 > 12) ? 100 : 101,
260 1.1 rillig
261 1.1 rillig /*
262 1.4 rillig * The 7 is part of the integer constant expression, but it is
263 1.4 rillig * irrelevant for the final result. The expression in parentheses
264 1.4 rillig * is an integer constant expression with value 1 and thus is a
265 1.4 rillig * bool constant expression.
266 1.1 rillig */
267 1.1 rillig Q2 = (13 > 12 ? 1 : 7) ? 100 : 101,
268 1.1 rillig
269 1.1 rillig BINAND = 0 & 1, /* ok */
270 1.1 rillig
271 1.1 rillig BINXOR = 0 ^ 1, /* ok */
272 1.1 rillig
273 1.1 rillig BINOR = 0 | 1, /* ok */
274 1.1 rillig
275 1.1 rillig LOGOR = 0 || 1, /* ok */
276 1.1 rillig
277 1.1 rillig LOGAND = 0 && 1, /* ok */
278 1.1 rillig };
279 1.2 rillig
280 1.3 rillig /*
281 1.3 rillig * An efficient implementation technique for a collection of boolean flags
282 1.3 rillig * is an enum. The enum declaration groups the available constants, and as
283 1.3 rillig * of 2020, compilers such as GCC and Clang have basic support for detecting
284 1.3 rillig * type mismatches on enums.
285 1.3 rillig */
286 1.3 rillig
287 1.3 rillig enum Flags {
288 1.3 rillig FLAG0 = 1 << 0,
289 1.3 rillig FLAG1 = 1 << 1,
290 1.3 rillig FLAG28 = 1 << 28
291 1.2 rillig };
292 1.2 rillig
293 1.2 rillig /*
294 1.3 rillig * The usual way to query one of the flags is demonstrated below.
295 1.3 rillig */
296 1.3 rillig
297 1.4 rillig extern void
298 1.4 rillig println(const char *);
299 1.3 rillig
300 1.3 rillig void
301 1.3 rillig query_flag_from_enum_bit_set(enum Flags flags)
302 1.3 rillig {
303 1.3 rillig
304 1.3 rillig if (flags & FLAG0)
305 1.3 rillig println("FLAG0 is set");
306 1.3 rillig
307 1.3 rillig if ((flags & FLAG1) != 0)
308 1.3 rillig println("FLAG1 is set");
309 1.3 rillig
310 1.3 rillig if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
311 1.3 rillig println("FLAG0 and FLAG1 are both set");
312 1.4 rillig
313 1.3 rillig if (flags & FLAG0 && flags & FLAG1)
314 1.3 rillig println("FLAG0 and FLAG1 are both set");
315 1.3 rillig
316 1.3 rillig if ((flags & (FLAG0 | FLAG1)) != 0)
317 1.3 rillig println("At least one of FLAG0 and FLAG1 is set");
318 1.3 rillig
319 1.3 rillig if (flags & FLAG28)
320 1.3 rillig println("FLAG28 is set");
321 1.3 rillig }
322 1.3 rillig
323 1.3 rillig /*
324 1.3 rillig * In all the above conditions (or controlling expressions, as the C standard
325 1.3 rillig * calls them), the result of the operator '&' is compared against 0. This
326 1.3 rillig * makes this pattern work, no matter whether the bits are in the low-value
327 1.3 rillig * range or in the high-value range (such as FLAG28, which has the value
328 1.4 rillig * 1073741824, which is more than what would fit into an unsigned char).
329 1.4 rillig * Even if an enum could be extended to larger types than int, this pattern
330 1.3 rillig * would work.
331 1.3 rillig */
332 1.3 rillig
333 1.3 rillig /*
334 1.3 rillig * There is a crucial difference between a _Bool variable and an ordinary
335 1.4 rillig * integer variable. C99 6.3.1.2 defines a conversion from an arbitrary
336 1.4 rillig * scalar value to _Bool as equivalent to (value != 0 ? 1 : 0). This means
337 1.4 rillig * that even if _Bool is implemented as an 8-bit unsigned integer, assigning
338 1.4 rillig * 256 to it would still result in the value 1 being stored. Storing 256 in
339 1.4 rillig * an ordinary 8-bit unsigned integer would result in the value 0 being
340 1.4 rillig * stored. See the test d_c99_bool.c for more details.
341 1.2 rillig *
342 1.3 rillig * Because of this, expressions like (flags & FLAG28) are only allowed in
343 1.3 rillig * bool context if they are guaranteed not to be truncated, even if the
344 1.3 rillig * result were to be stored in a plain unsigned integer.
345 1.2 rillig */
346 1.3 rillig
347 1.4 rillig /*ARGSUSED*/
348 1.3 rillig void
349 1.3 rillig SB007_allow_flag_test_on_bit_set_enums(enum Flags flags)
350 1.3 rillig {
351 1.3 rillig bool b;
352 1.3 rillig
353 1.3 rillig /*
354 1.4 rillig * FLAG0 has the value 1 and thus can be stored in a bool variable
355 1.4 rillig * without truncation. Nevertheless this special case is not allowed
356 1.4 rillig * because it would be too confusing if FLAG0 would work and all the
357 1.4 rillig * other flags wouldn't.
358 1.3 rillig */
359 1.4 rillig b = flags & FLAG0; /* expect: 107 */
360 1.3 rillig
361 1.3 rillig /*
362 1.3 rillig * Assuming that FLAG1 is set in flags, a _Bool variable stores this
363 1.4 rillig * as 1, as defined by C99 6.3.1.2. A uint8_t variable would store
364 1.4 rillig * it as 2, as that is the integer value of FLAG1. Since FLAG1 fits
365 1.4 rillig * in a uint8_t, no truncation takes place.
366 1.3 rillig */
367 1.4 rillig b = flags & FLAG1; /* expect: 107 */
368 1.3 rillig
369 1.3 rillig /*
370 1.4 rillig * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
371 1.4 rillig * zero. In a uint8_t, the stored value would be 0 since bit 28 is
372 1.4 rillig * out of range for a uint8_t and thus gets truncated.
373 1.3 rillig */
374 1.4 rillig b = flags & FLAG28; /* expect: 107 */
375 1.3 rillig }
376 1.3 rillig
377 1.3 rillig /* A bool bit field is compatible with bool. Other bit fields are not. */
378 1.3 rillig
379 1.3 rillig struct flags {
380 1.3 rillig bool bool_flag: 1;
381 1.3 rillig unsigned uint_flag: 1;
382 1.3 rillig };
383 1.3 rillig
384 1.4 rillig /*ARGSUSED*/
385 1.3 rillig void
386 1.4 rillig SB008_bit_fields(const struct flags *flags)
387 1.2 rillig {
388 1.3 rillig bool b;
389 1.3 rillig
390 1.3 rillig b = flags->bool_flag; /* ok */
391 1.4 rillig b = flags->uint_flag; /* expect: 107 */
392 1.4 rillig flags->bool_flag = b;
393 1.4 rillig flags->uint_flag = b; /* expect: 107 */
394 1.3 rillig }
395 1.3 rillig
396 1.3 rillig /* Test implicit conversion when returning a value from a function. */
397 1.3 rillig
398 1.4 rillig /*ARGSUSED*/
399 1.3 rillig bool
400 1.3 rillig returning_bool(bool b, int i, const char *p)
401 1.3 rillig {
402 1.3 rillig if (i > 0)
403 1.3 rillig return b; /* ok */
404 1.3 rillig if (i < 0)
405 1.4 rillig return i; /* expect: 211 */
406 1.4 rillig return p; /* expect: 211 */
407 1.3 rillig }
408 1.3 rillig
409 1.4 rillig /*ARGSUSED*/
410 1.3 rillig char
411 1.3 rillig returning_char(bool b, int i, const char *p)
412 1.3 rillig {
413 1.3 rillig if (i > 0)
414 1.4 rillig return b; /* expect: 211 */
415 1.3 rillig if (i < 0)
416 1.4 rillig return i; /* XXX: narrowing conversion */
417 1.4 rillig return p; /* expect: 183 */
418 1.4 rillig }
419 1.4 rillig
420 1.4 rillig bool
421 1.4 rillig return_constant_false(void)
422 1.4 rillig {
423 1.4 rillig return 0;
424 1.4 rillig }
425 1.4 rillig
426 1.4 rillig bool
427 1.4 rillig return_constant_true(void)
428 1.4 rillig {
429 1.4 rillig return 1;
430 1.4 rillig }
431 1.4 rillig
432 1.4 rillig bool
433 1.4 rillig return_invalid_integer(void)
434 1.4 rillig {
435 1.4 rillig return 2; /* expect: 211 */
436 1.3 rillig }
437 1.3 rillig
438 1.3 rillig /* Test passing arguments to a function. */
439 1.3 rillig
440 1.4 rillig extern void
441 1.4 rillig taking_arguments(bool, int, const char *, ...);
442 1.3 rillig
443 1.3 rillig void
444 1.3 rillig passing_arguments(bool b, int i, const char *p)
445 1.3 rillig {
446 1.3 rillig /* No conversion necessary. */
447 1.3 rillig taking_arguments(b, i, p);
448 1.3 rillig
449 1.3 rillig /* Implicitly converting bool to other scalar types. */
450 1.4 rillig taking_arguments(b, b, b); /* expect: 334, 334 */
451 1.3 rillig
452 1.3 rillig /* Implicitly converting int to bool (arg #1). */
453 1.4 rillig taking_arguments(i, i, i); /* expect: 334, 154 */
454 1.3 rillig
455 1.3 rillig /* Implicitly converting pointer to bool (arg #1). */
456 1.4 rillig taking_arguments(p, p, p); /* expect: 334, 154 */
457 1.3 rillig
458 1.3 rillig /* Passing bool as vararg. */
459 1.4 rillig taking_arguments(b, i, p, b, i, p); /* expect: arg#4 */ // TODO
460 1.4 rillig
461 1.4 rillig /* Passing a bool constant. */
462 1.4 rillig taking_arguments(0, i, p);
463 1.4 rillig
464 1.4 rillig /* Passing a bool constant. */
465 1.4 rillig taking_arguments(1, i, p);
466 1.4 rillig
467 1.4 rillig /* Trying to pass an invalid integer. */
468 1.4 rillig taking_arguments(2, i, p); /* expect: 334 */
469 1.4 rillig }
470 1.4 rillig
471 1.4 rillig /*
472 1.4 rillig * This is just normal access to a bool member of a struct, to ensure that
473 1.4 rillig * these produce no errors.
474 1.4 rillig */
475 1.4 rillig void
476 1.4 rillig struct_access_operators(void)
477 1.4 rillig {
478 1.4 rillig struct bool_struct {
479 1.4 rillig bool b;
480 1.4 rillig };
481 1.4 rillig
482 1.4 rillig /* Initialize and assign using boolean constants. */
483 1.4 rillig bool b = 0;
484 1.4 rillig b = 1;
485 1.4 rillig
486 1.4 rillig /* Access a struct member using the '.' operator. */
487 1.4 rillig struct bool_struct bs = { 1 };
488 1.4 rillig b = bs.b;
489 1.4 rillig bs.b = b;
490 1.4 rillig bs.b = 0;
491 1.4 rillig
492 1.4 rillig /* Access a struct member using the '->' operator. */
493 1.4 rillig struct bool_struct *bsp = &bs;
494 1.4 rillig b = bsp->b;
495 1.4 rillig bsp->b = b;
496 1.4 rillig bsp->b = 0;
497 1.4 rillig
498 1.4 rillig /* Taking the address of a bool lvalue. */
499 1.4 rillig bool *bp;
500 1.4 rillig bp = &b;
501 1.4 rillig *bp = b;
502 1.4 rillig b = *bp;
503 1.4 rillig }
504 1.4 rillig
505 1.4 rillig /*
506 1.4 rillig * Comparing a _Bool expression to 0 or 1 is redundant. It may come from
507 1.4 rillig * an earlier version of the code, before it got migrated to using _Bool.
508 1.4 rillig * Usually, bool expressions are used directly as control expressions or
509 1.4 rillig * as argument to the boolean operators such as '!', '&&', '||'.
510 1.4 rillig *
511 1.4 rillig * Since lint steps in after the C preprocessor, it has no chance of seeing
512 1.4 rillig * the original source code, which may well have been "b == false" instead
513 1.4 rillig * of "b == 0".
514 1.4 rillig */
515 1.4 rillig bool
516 1.4 rillig compare_var_with_constant(bool b)
517 1.4 rillig {
518 1.4 rillig bool t1 = b == 0;
519 1.4 rillig bool t2 = t1 != 0;
520 1.4 rillig bool t3 = t2 == 1;
521 1.4 rillig bool t4 = t3 != 1;
522 1.4 rillig return t4 ^ t3;
523 1.2 rillig }
524