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