Home | History | Annotate | Line # | Download | only in lint1
d_c99_bool_strict.c revision 1.25
      1 /*	$NetBSD: d_c99_bool_strict.c,v 1.25 2021/03/21 14:12:46 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, as in lint1/ops.def.
    155 	 *
    156 	 * TODO: figure out an elegant way to achieve the same effect in
    157 	 *  strict bool mode.
    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, 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, 55 */
    181 	LOGOR_INT = 0 || 1,	/* expect: 331, 332 */
    182 
    183 	LOGAND_BOOL = __lint_false && __lint_true, /* expect: 161, 55 */
    184 	LOGAND_INT = 0 && 1,	/* expect: 331, 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, 334 */
    302 
    303 	/* Implicitly converting int to bool (arg #1). */
    304 	take_arguments(i, i, i);	/* expect: 334, 154 */
    305 
    306 	/* Implicitly converting pointer to bool (arg #1). */
    307 	take_arguments(p, p, p);	/* expect: 334, 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();
    369 
    370 	if (__lint_true)	/* expect: 161 */
    371 		do_nothing();
    372 
    373 	if (b)
    374 		do_nothing();
    375 
    376 	if (0)			/* expect: 333 */
    377 		do_nothing();
    378 
    379 	if (1)			/* expect: 333 */
    380 		do_nothing();
    381 
    382 	if (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, 239 */
    420 	b = !__lint_true;	/* expect: 161, 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 /*
    443  * strict-bool-operand-binary:
    444  *	Operator	left:	bool?	other?	right:	bool?	other?
    445  *	.			-	yes		yes	yes
    446  *	->			-	yes		yes	yes
    447  *	<=, <, >=, >		-	yes		-	yes
    448  *	==, !=			yes	yes		yes	yes
    449  *	&			yes	yes		yes	yes
    450  *	^			yes	yes		yes	yes
    451  *	|			yes	yes		yes	yes
    452  *	&&			yes	-		yes	-
    453  *	||			yes	-		yes	-
    454  *	?			yes	-		yes	yes
    455  *	:			yes	yes		yes	yes
    456  *	=			yes	yes		yes	yes
    457  *	&=, ^=, |=		yes	yes		yes	yes
    458  *	,			yes	yes		yes	yes
    459  *	The other binary operators do not accept bool operands.
    460  */
    461 
    462 /*
    463  * Ensure that bool members can be accessed as usual.
    464  */
    465 void
    466 strict_bool_operand_binary_dot_arrow(void)
    467 {
    468 	struct bool_struct {
    469 		bool b;
    470 	};
    471 
    472 	/* Initialize and assign using boolean constants. */
    473 	bool b = __lint_false;
    474 	b = __lint_true;
    475 
    476 	/* Access a struct member using the '.' operator. */
    477 	struct bool_struct bs = { __lint_true };
    478 	b = bs.b;
    479 	bs.b = b;
    480 	bs.b = 0;		/* expect: 107 */
    481 
    482 	/* Access a struct member using the '->' operator. */
    483 	struct bool_struct *bsp = &bs;
    484 	b = bsp->b;
    485 	bsp->b = b;
    486 	bsp->b = 0;		/* expect: 107 */
    487 }
    488 
    489 int
    490 strict_bool_operand_binary(bool b, int i)
    491 {
    492 
    493 	/* The right-hand sides of these assignments are ok. */
    494 	b = !b;
    495 	b = b && b;
    496 	b = b || b;
    497 
    498 	/*
    499 	 * The right-hand sides of these assignments implicitly convert from
    500 	 * scalar to bool.
    501 	 */
    502 	b = !i;			/* expect: 330 */
    503 	b = i && i;		/* expect: 331, 332 */
    504 	b = i || i;		/* expect: 331, 332 */
    505 
    506 	b = b && 0;		/* expect: 332 */
    507 	b = 0 && b;		/* expect: 331 */
    508 	b = b || 0;		/* expect: 332 */
    509 	b = 0 || b;		/* expect: 331 */
    510 
    511 	return i;
    512 }
    513 
    514 void
    515 strict_bool_operand_binary_all(bool b, unsigned u)
    516 {
    517 	b = !b;
    518 	b = ~b;			/* expect: 335 */
    519 	++b;			/* expect: 335 */
    520 	--b;			/* expect: 335 */
    521 	b++;			/* expect: 335 */
    522 	b--;			/* expect: 335 */
    523 	b = +b;			/* expect: 335 */
    524 	b = -b;			/* expect: 335 */
    525 
    526 	b = b * b;		/* expect: 336, 337 */
    527 	b = b / b;		/* expect: 336, 337 */
    528 	b = b % b;		/* expect: 336, 337 */
    529 	b = b + b;		/* expect: 336, 337 */
    530 	b = b - b;		/* expect: 336, 337 */
    531 	b = b << b;		/* expect: 336, 337 */
    532 	b = b >> b;		/* expect: 336, 337 */
    533 
    534 	b = b < b;		/* expect: 336, 337 */
    535 	b = b <= b;		/* expect: 336, 337 */
    536 	b = b > b;		/* expect: 336, 337 */
    537 	b = b >= b;		/* expect: 336, 337 */
    538 	b = b == b;
    539 	b = b != b;
    540 
    541 	b = b & b;
    542 	b = b ^ b;
    543 	b = b | b;
    544 	b = b && b;
    545 	b = b || b;
    546 	b = b ? b : b;
    547 
    548 	b = b;
    549 	b *= b;			/* expect: 336, 337 */
    550 	b /= b;			/* expect: 336, 337 */
    551 	b %= b;			/* expect: 336, 337 */
    552 	b += b;			/* expect: 336, 337 */
    553 	b -= b;			/* expect: 336, 337 */
    554 	b <<= b;		/* expect: 336, 337 */
    555 	b >>= b;		/* expect: 336, 337 */
    556 	b &= b;
    557 	b ^= b;
    558 	b |= b;
    559 
    560 	/* Operations with mixed types. */
    561 	u = b * u;		/* expect: 336 */
    562 	u = u * b;		/* expect: 337 */
    563 	u = b / u;		/* expect: 336 */
    564 	u = u / b;		/* expect: 337 */
    565 	u = b % u;		/* expect: 336 */
    566 	u = u % b;		/* expect: 337 */
    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 : u;
    576 	u = b ? b : u;		/* expect: 107 */
    577 	u = b ? u : b;		/* expect: 107 */
    578 }
    579 
    580 bool
    581 strict_bool_operand_binary_comma(bool b, int i)
    582 {
    583 	b = (b, !b);		/* expect: 129 */
    584 	i = (i, i + 1);		/* expect: 129 */
    585 	return b;
    586 }
    587 
    588 /*
    589  * strict-bool-operator-result:
    590  *	The result type of the operators '!', '<', '<=', '>', '>=',
    591  *	'==', '!=', '&&', '||' is _Bool instead of int.
    592  */
    593 
    594 void
    595 strict_bool_operator_result(bool b)
    596 {
    597 	char c = b;		/* expect: 107 */
    598 	int i = b;		/* expect: 107 */
    599 	double d = b;		/* expect: 107 */
    600 	void *p = b;		/* expect: 107 */
    601 
    602 	/* The right-hand sides of these assignments are all ok. */
    603 	b = !b;
    604 	b = i == i;
    605 	b = i != i;
    606 	b = i < i;
    607 	b = i <= i;
    608 	b = i >= i;
    609 	b = i > i;
    610 	b = b && b;
    611 	b = b || b;
    612 
    613 	/*
    614 	 * The right-hand sides of these assignments are not ok, they
    615 	 * implicitly convert from bool to int.
    616 	 */
    617 	i = !b;			/* expect: 107 */
    618 	i = i == i;		/* expect: 107 */
    619 	i = i != i;		/* expect: 107 */
    620 	i = i < i;		/* expect: 107 */
    621 	i = i <= i;		/* expect: 107 */
    622 	i = i >= i;		/* expect: 107 */
    623 	i = i > i;		/* expect: 107 */
    624 	i = b && b;		/* expect: 107 */
    625 	i = b || b;		/* expect: 107 */
    626 }
    627 
    628 
    629 /*
    630  * strict-bool-bitwise-and:
    631  *	Expressions of the form "flags & FLAG" are compatible with _Bool if
    632  *	the left operand has enum type, the right operand is an integer
    633  *	constant and the resulting value is used in a context where it is
    634  *	implicitly and immediately compared to zero.
    635  *
    636  *	Note: Examples for such contexts are controlling expressions or the
    637  *	operands of the operators '!', '&&', '||'.
    638  *
    639  *	Note: Counterexamples for contexts are assignments to a bool variable.
    640  *
    641  *	Note: These rules ensure that conforming code can be compiled without
    642  *	change in behavior using old compilers that implement bool as an
    643  *	ordinary integer type, without the special rule C99 6.3.1.2.
    644  */
    645 
    646 enum Flags {
    647 	FLAG0 = 1 << 0,
    648 	FLAG1 = 1 << 1,
    649 	FLAG28 = 1 << 28
    650 };
    651 
    652 void
    653 strict_bool_bitwise_and_enum(enum Flags flags) /* expect: 231 */
    654 {
    655 	bool b;
    656 
    657 	/*
    658 	 * FLAG0 has the value 1 and thus can be stored in a bool variable
    659 	 * without truncation.  Nevertheless this special case is not allowed
    660 	 * because it would be too confusing if FLAG0 would work and all the
    661 	 * other flags wouldn't.
    662 	 */
    663 	b = flags & FLAG0;	/* expect: 107 */
    664 
    665 	/*
    666 	 * Assuming that FLAG1 is set in flags, a _Bool variable stores this
    667 	 * as 1, as defined by C99 6.3.1.2.  A uint8_t variable would store
    668 	 * it as 2, as that is the integer value of FLAG1.  Since FLAG1 fits
    669 	 * in a uint8_t, no truncation takes place.
    670 	 */
    671 	b = flags & FLAG1;	/* expect: 107 */
    672 
    673 	/*
    674 	 * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
    675 	 * zero.  In a uint8_t, the stored value would be 0 since bit 28 is
    676 	 * out of range for a uint8_t and thus gets truncated.
    677 	 */
    678 	b = flags & FLAG28;	/* expect: 107 */
    679 }
    680 
    681 /*
    682  * Demonstrate idiomatic code to query flags from an enum bit set.
    683  *
    684  * In all the controlling expressions in this function, the result of the
    685  * operator '&' is compared against 0.  This makes this pattern work, no
    686  * matter whether the bits are in the low-value range or in the high-value
    687  * range (such as FLAG28, which has the value 1073741824, which is more than
    688  * what would fit into an unsigned char).  Even if an enum could be extended
    689  * to larger types than int, this pattern would work.
    690  */
    691 void
    692 query_flag_from_enum_bit_set(enum Flags flags)
    693 {
    694 	if (flags & FLAG0)
    695 		println("FLAG0 is set");
    696 
    697 	if ((flags & FLAG1) != 0)
    698 		println("FLAG1 is set");
    699 
    700 	if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
    701 		println("FLAG0 and FLAG1 are both set");
    702 
    703 	if (flags & FLAG0 && flags & FLAG1)
    704 		println("FLAG0 and FLAG1 are both set");
    705 
    706 	if ((flags & (FLAG0 | FLAG1)) != 0)
    707 		println("At least one of FLAG0 and FLAG1 is set");
    708 
    709 	if (flags & FLAG28)
    710 		println("FLAG28 is set");
    711 }
    712 
    713 
    714 void
    715 strict_bool_operator_eq_bool_int(void)
    716 {
    717 	(void)(strict_bool_conversion_return_false() == 0); /* expect: 107 */
    718 }
    719 
    720 void
    721 strict_bool_assign_bit_field_then_compare(void)
    722 {
    723 	struct s {
    724 		bool flag: 1;
    725 	};
    726 
    727 	struct s s = { __lint_false };
    728 
    729 	(void)((s.flag = s.flag) != __lint_false);	/* expect: 129 */
    730 }
    731 
    732 void
    733 bool_as_array_index(bool cond)
    734 {
    735 	static const char *repr[] = { "no", "yes" };
    736 	/*
    737 	 * The '+' in the error message reveals that lint internally
    738 	 * translates 'arr[ind]' to '*(arr + ind)' in an early stage of
    739 	 * parsing.
    740 	 */
    741 	println(repr[cond]);		/* expect: 337 */
    742 	println(cond ? "yes" : "no");
    743 }
    744 
    745 void
    746 do_while_false(void)
    747 {
    748 	do {
    749 
    750 	} while (__lint_false);
    751 }
    752 
    753 void
    754 do_while_true(void)
    755 {
    756 	do {
    757 
    758 	} while (__lint_true);	/* expect: 161 */
    759 }
    760 
    761 void
    762 initialization(void)
    763 {
    764 	struct {
    765 		_Bool b;
    766 	} var[] = {
    767 	    { __lint_false },
    768 	    { __lint_true },
    769 	    { 0 },		/* expect: 107 */
    770 	    { 1 },		/* expect: 107 */
    771 	};
    772 }
    773