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