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