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