Home | History | Annotate | Line # | Download | only in lint1
d_c99_bool_strict.c revision 1.7
      1  1.7  rillig /*	$NetBSD: d_c99_bool_strict.c,v 1.7 2021/01/15 23:15:28 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.4  rillig  * This means:
      7  1.1  rillig  *
      8  1.1  rillig  * SB001: Controlling expressions in 'if', 'while', 'for', '?:' must be of
      9  1.1  rillig  * type _Bool instead of scalar.
     10  1.1  rillig  *
     11  1.1  rillig  * SB002: The operators '!', '==', '!=', '<', '<=', '>=', '>', '&&', '||'
     12  1.1  rillig  * return _Bool instead of int.
     13  1.1  rillig  *
     14  1.1  rillig  * SB003: The operators '!', '&&', '||' take _Bool instead of scalar.
     15  1.1  rillig  *
     16  1.1  rillig  * SB004: The only operators that take _Bool are '!', '==', '!=',
     17  1.1  rillig  * '&', '^', '|', '&&', '||', '?', ':', '=', '&=', '^=', '|='.
     18  1.1  rillig  *
     19  1.1  rillig  * SB005: There is no implicit conversion from _Bool to any other type.
     20  1.1  rillig  *
     21  1.4  rillig  * SB006: An expression is compatible with type _Bool if its main operator
     22  1.4  rillig  * returns type _Bool, or if the expression is an integer constant expression
     23  1.4  rillig  * with value 0 or 1.
     24  1.3  rillig  *
     25  1.3  rillig  * SB007: Expressions like "flags & FLAG" are compatible with _Bool if
     26  1.3  rillig  * they appear in a context where they are immediately compared to zero.
     27  1.3  rillig  * Assigning to a _Bool variable does not count as such a context, to
     28  1.3  rillig  * allow programs to be compiled without silent changes on a compiler that
     29  1.3  rillig  * is lacking the special _Bool type.
     30  1.3  rillig  *
     31  1.3  rillig  * SB008: Bit fields in struct may be based on _Bool.  These bit fields
     32  1.3  rillig  * typically have type _Bool:1 and can be converted to _Bool and back.
     33  1.1  rillig  */
     34  1.1  rillig 
     35  1.4  rillig /* lint1-extra-flags: -T */
     36  1.1  rillig 
     37  1.1  rillig /*
     38  1.1  rillig  * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and
     39  1.1  rillig  * true = 1.  Therefore, constant expressions of integer type have to be
     40  1.1  rillig  * regarded as possible boolean constants if their value is either 0 or 1.
     41  1.1  rillig  * At this point of the translation, the preprocessor has already removed
     42  1.1  rillig  * the words "false" and "true" from the source code.
     43  1.1  rillig  */
     44  1.1  rillig 
     45  1.1  rillig /*
     46  1.1  rillig  * Using a typedef for bool does not hurt the checks, they all use the
     47  1.1  rillig  * underlying basic type (see tspec_t), which is BOOL.
     48  1.1  rillig  */
     49  1.1  rillig typedef _Bool bool;
     50  1.1  rillig 
     51  1.1  rillig void
     52  1.1  rillig SB001_controlling_expression(bool b, int i, double d, const void *p)
     53  1.1  rillig {
     54  1.1  rillig 
     55  1.1  rillig 	/* Fine due to SB006. */
     56  1.1  rillig 	if (/*CONSTCOND*/0)
     57  1.1  rillig 		return;
     58  1.1  rillig 
     59  1.1  rillig 	/* Fine due to SB006. */
     60  1.1  rillig 	if (/*CONSTCOND*/1)
     61  1.1  rillig 		return;
     62  1.1  rillig 
     63  1.1  rillig 	/* Not allowed: 2 is not a boolean expression. */
     64  1.4  rillig 	if (/*CONSTCOND*/2)	/* expect: 333 */
     65  1.1  rillig 		return;
     66  1.1  rillig 
     67  1.1  rillig 	/* Not allowed: There is no implicit conversion from scalar to bool. */
     68  1.4  rillig 	if (i)			/* expect: 333 */
     69  1.1  rillig 		return;
     70  1.1  rillig 	if (i != 0)
     71  1.1  rillig 		return;
     72  1.1  rillig 
     73  1.1  rillig 	/* Not allowed: There is no implicit conversion from scalar to bool. */
     74  1.4  rillig 	if (d)			/* expect: 333 */
     75  1.1  rillig 		return;
     76  1.1  rillig 	if (d != 0.0)
     77  1.1  rillig 		return;
     78  1.1  rillig 
     79  1.1  rillig 	/* Not allowed: There is no implicit conversion from scalar to bool. */
     80  1.4  rillig 	if (p)			/* expect: 333 */
     81  1.1  rillig 		return;
     82  1.1  rillig 	if (p != (void *)0)
     83  1.1  rillig 		return;
     84  1.1  rillig 
     85  1.1  rillig 	/* Using a bool expression is allowed. */
     86  1.1  rillig 	if (b)
     87  1.1  rillig 		return;
     88  1.1  rillig }
     89  1.1  rillig 
     90  1.1  rillig void
     91  1.4  rillig SB002_operator_result_type(bool b)
     92  1.1  rillig {
     93  1.1  rillig 	b = b;
     94  1.4  rillig 	char c = b;		/* expect: 107 */
     95  1.4  rillig 	int i = b;		/* expect: 107 */
     96  1.4  rillig 	double d = b;		/* expect: 107 */
     97  1.4  rillig 	void *p = b;		/* expect: 107 */
     98  1.1  rillig 
     99  1.4  rillig 	/* The right-hand sides of these assignments are all ok. */
    100  1.1  rillig 	b = !b;
    101  1.1  rillig 	b = i == i;
    102  1.1  rillig 	b = i != i;
    103  1.1  rillig 	b = i < i;
    104  1.1  rillig 	b = i <= i;
    105  1.1  rillig 	b = i >= i;
    106  1.1  rillig 	b = i > i;
    107  1.1  rillig 	b = b && b;
    108  1.1  rillig 	b = b || b;
    109  1.1  rillig 
    110  1.1  rillig 	/*
    111  1.4  rillig 	 * The right-hand sides of these assignments are not ok, they
    112  1.4  rillig 	 * implicitly convert from bool to int.
    113  1.1  rillig 	 */
    114  1.4  rillig 	i = !b;			/* expect: 107 */
    115  1.4  rillig 	i = i == i;		/* expect: 107 */
    116  1.4  rillig 	i = i != i;		/* expect: 107 */
    117  1.4  rillig 	i = i < i;		/* expect: 107 */
    118  1.4  rillig 	i = i <= i;		/* expect: 107 */
    119  1.4  rillig 	i = i >= i;		/* expect: 107 */
    120  1.4  rillig 	i = i > i;		/* expect: 107 */
    121  1.4  rillig 	i = b && b;		/* expect: 107 */
    122  1.4  rillig 	i = b || b;		/* expect: 107 */
    123  1.1  rillig }
    124  1.1  rillig 
    125  1.4  rillig int
    126  1.1  rillig SB003_operands(bool b, int i)
    127  1.1  rillig {
    128  1.1  rillig 
    129  1.4  rillig 	/* The right-hand sides of these assignments are ok. */
    130  1.1  rillig 	b = !b;
    131  1.1  rillig 	b = b && b;
    132  1.1  rillig 	b = b || b;
    133  1.1  rillig 
    134  1.4  rillig 	/*
    135  1.4  rillig 	 * The right-hand sides of these assignments implicitly convert from
    136  1.4  rillig 	 * scalar to bool.
    137  1.4  rillig 	 */
    138  1.4  rillig 	b = !i;			/* expect: 330 */
    139  1.4  rillig 	b = i && i;		/* expect: 331, 332 */
    140  1.4  rillig 	b = i || i;		/* expect: 331, 332 */
    141  1.4  rillig 
    142  1.4  rillig 	b = b && 0;
    143  1.4  rillig 	b = 0 && b;
    144  1.4  rillig 	b = b || 0;
    145  1.4  rillig 	b = 0 || b;
    146  1.4  rillig 
    147  1.4  rillig 	return i;
    148  1.1  rillig }
    149  1.1  rillig 
    150  1.4  rillig /*ARGSUSED*/
    151  1.1  rillig void
    152  1.4  rillig SB004_operators_and_bool_operands(bool b, unsigned u)
    153  1.1  rillig {
    154  1.1  rillig 	b = !b;			/* ok */
    155  1.4  rillig 	b = ~b;			/* expect: 335 */
    156  1.4  rillig 	++b;			/* expect: 335 */
    157  1.4  rillig 	--b;			/* expect: 335 */
    158  1.4  rillig 	b++;			/* expect: 335 */
    159  1.4  rillig 	b--;			/* expect: 335 */
    160  1.4  rillig 	b = +b;			/* expect: 335 */
    161  1.4  rillig 	b = -b;			/* expect: 335 */
    162  1.4  rillig 
    163  1.4  rillig 	b = b * b;		/* expect: 336, 337 */
    164  1.4  rillig 	b = b / b;		/* expect: 336, 337 */
    165  1.4  rillig 	b = b % b;		/* expect: 336, 337 */
    166  1.4  rillig 	b = b + b;		/* expect: 336, 337 */
    167  1.4  rillig 	b = b - b;		/* expect: 336, 337 */
    168  1.4  rillig 	b = b << b;		/* expect: 336, 337 */
    169  1.4  rillig 	b = b >> b;		/* expect: 336, 337 */
    170  1.4  rillig 
    171  1.4  rillig 	b = b < b;		/* expect: 336, 337 */
    172  1.4  rillig 	b = b <= b;		/* expect: 336, 337 */
    173  1.4  rillig 	b = b > b;		/* expect: 336, 337 */
    174  1.4  rillig 	b = b >= b;		/* expect: 336, 337 */
    175  1.1  rillig 	b = b == b;		/* ok */
    176  1.1  rillig 	b = b != b;		/* ok */
    177  1.1  rillig 
    178  1.1  rillig 	b = b & b;		/* ok */
    179  1.1  rillig 	b = b ^ b;		/* ok */
    180  1.1  rillig 	b = b | b;		/* ok */
    181  1.1  rillig 	b = b && b;		/* ok */
    182  1.1  rillig 	b = b || b;		/* ok */
    183  1.1  rillig 	b = b ? b : b;		/* ok */
    184  1.1  rillig 
    185  1.1  rillig 	b = b;			/* ok */
    186  1.4  rillig 	b *= b;			/* expect: 336, 337 */
    187  1.4  rillig 	b /= b;			/* expect: 336, 337 */
    188  1.4  rillig 	b %= b;			/* expect: 336, 337 */
    189  1.4  rillig 	b += b;			/* expect: 336, 337 */
    190  1.4  rillig 	b -= b;			/* expect: 336, 337 */
    191  1.4  rillig 	b <<= b;		/* expect: 336, 337 */
    192  1.4  rillig 	b >>= b;		/* expect: 336, 337 */
    193  1.1  rillig 	b &= b;			/* ok */
    194  1.1  rillig 	b ^= b;			/* ok */
    195  1.1  rillig 	b |= b;			/* ok */
    196  1.1  rillig 
    197  1.1  rillig 	/* Operations with mixed types. */
    198  1.4  rillig 	u = b * u;		/* expect: 336 */
    199  1.4  rillig 	u = u * b;		/* expect: 337 */
    200  1.4  rillig 	u = b / u;		/* expect: 336 */
    201  1.4  rillig 	u = u / b;		/* expect: 337 */
    202  1.4  rillig 	u = b % u;		/* expect: 336 */
    203  1.4  rillig 	u = u % b;		/* expect: 337 */
    204  1.4  rillig 	u = b + u;		/* expect: 336 */
    205  1.4  rillig 	u = u + b;		/* expect: 337 */
    206  1.4  rillig 	u = b - u;		/* expect: 336 */
    207  1.4  rillig 	u = u - b;		/* expect: 337 */
    208  1.4  rillig 	u = b << u;		/* expect: 336 */
    209  1.4  rillig 	u = u << b;		/* expect: 337 */
    210  1.4  rillig 	u = b >> u;		/* expect: 336 */
    211  1.4  rillig 	u = u >> b;		/* expect: 337 */
    212  1.1  rillig 	u = b ? u : u;		/* ok */
    213  1.4  rillig 	u = b ? b : u;		/* expect: 107 */
    214  1.4  rillig 	u = b ? u : b;		/* expect: 107 */
    215  1.1  rillig }
    216  1.1  rillig 
    217  1.4  rillig /*ARGSUSED*/
    218  1.1  rillig void
    219  1.1  rillig SB005_convert_from_bool_to_scalar(bool b)
    220  1.1  rillig {
    221  1.1  rillig 	int i;
    222  1.1  rillig 	unsigned u;
    223  1.1  rillig 	double d;
    224  1.1  rillig 	void *p;
    225  1.1  rillig 
    226  1.4  rillig 	i = b;			/* expect: 107 */
    227  1.4  rillig 	u = b;			/* expect: 107 */
    228  1.4  rillig 	d = b;			/* expect: 107 */
    229  1.4  rillig 	p = b;			/* expect: 107 */
    230  1.1  rillig }
    231  1.1  rillig 
    232  1.1  rillig enum SB006_bool_constant_expression {
    233  1.1  rillig 	/* Ok: 0 is a boolean constant expression. */
    234  1.1  rillig 	INT0 = 0 ? 100 : 101,
    235  1.1  rillig 
    236  1.1  rillig 	/* Ok: 1 is a boolean constant expression. */
    237  1.1  rillig 	INT1 = 1 ? 100 : 101,
    238  1.1  rillig 
    239  1.1  rillig 	/* Not ok: 2 is not a boolean constant (neither 0 nor 1). */
    240  1.4  rillig 	INT2 = 2 ? 100 : 101,	/* expect: 331 */
    241  1.1  rillig 
    242  1.1  rillig 	/*
    243  1.4  rillig 	 * The intermediate expression "2" has type int, which is not
    244  1.4  rillig 	 * compatible with _Bool.  The expression "2 - 2" is an integer
    245  1.4  rillig 	 * constant expression with value 0 and is thus a bool constant
    246  1.4  rillig 	 * expression.  This particular case probably does not occur in
    247  1.4  rillig 	 * practice.
    248  1.1  rillig 	 */
    249  1.1  rillig 	ARITH = (2 - 2) ? 100 : 101,
    250  1.1  rillig 
    251  1.1  rillig 	/*
    252  1.4  rillig 	 * These two variants of an expression can occur when a preprocessor
    253  1.4  rillig 	 * macro is either defined to 1 or left empty, as in lint1/ops.def.
    254  1.1  rillig 	 */
    255  1.4  rillig 	BINARY_PLUS = (1 + 0) ? 100 : 101,
    256  1.4  rillig 	UNARY_PLUS = (+0) ? 100 : 101,
    257  1.4  rillig 
    258  1.4  rillig 	/* The main operator '>' has return type bool. */
    259  1.1  rillig 	Q1 = (13 > 12) ? 100 : 101,
    260  1.1  rillig 
    261  1.1  rillig 	/*
    262  1.4  rillig 	 * The 7 is part of the integer constant expression, but it is
    263  1.4  rillig 	 * irrelevant for the final result.  The expression in parentheses
    264  1.4  rillig 	 * is an integer constant expression with value 1 and thus is a
    265  1.4  rillig 	 * bool constant expression.
    266  1.1  rillig 	 */
    267  1.1  rillig 	Q2 = (13 > 12 ? 1 : 7) ? 100 : 101,
    268  1.1  rillig 
    269  1.1  rillig 	BINAND = 0 & 1,		/* ok */
    270  1.1  rillig 
    271  1.1  rillig 	BINXOR = 0 ^ 1,		/* ok */
    272  1.1  rillig 
    273  1.1  rillig 	BINOR = 0 | 1,		/* ok */
    274  1.1  rillig 
    275  1.1  rillig 	LOGOR = 0 || 1,		/* ok */
    276  1.1  rillig 
    277  1.1  rillig 	LOGAND = 0 && 1,	/* ok */
    278  1.1  rillig };
    279  1.2  rillig 
    280  1.3  rillig /*
    281  1.3  rillig  * An efficient implementation technique for a collection of boolean flags
    282  1.3  rillig  * is an enum.  The enum declaration groups the available constants, and as
    283  1.3  rillig  * of 2020, compilers such as GCC and Clang have basic support for detecting
    284  1.3  rillig  * type mismatches on enums.
    285  1.3  rillig  */
    286  1.3  rillig 
    287  1.3  rillig enum Flags {
    288  1.3  rillig 	FLAG0 = 1 << 0,
    289  1.3  rillig 	FLAG1 = 1 << 1,
    290  1.3  rillig 	FLAG28 = 1 << 28
    291  1.2  rillig };
    292  1.2  rillig 
    293  1.2  rillig /*
    294  1.3  rillig  * The usual way to query one of the flags is demonstrated below.
    295  1.3  rillig  */
    296  1.3  rillig 
    297  1.4  rillig extern void
    298  1.4  rillig println(const char *);
    299  1.3  rillig 
    300  1.3  rillig void
    301  1.3  rillig query_flag_from_enum_bit_set(enum Flags flags)
    302  1.3  rillig {
    303  1.3  rillig 
    304  1.3  rillig 	if (flags & FLAG0)
    305  1.3  rillig 		println("FLAG0 is set");
    306  1.3  rillig 
    307  1.3  rillig 	if ((flags & FLAG1) != 0)
    308  1.3  rillig 		println("FLAG1 is set");
    309  1.3  rillig 
    310  1.3  rillig 	if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
    311  1.3  rillig 		println("FLAG0 and FLAG1 are both set");
    312  1.4  rillig 
    313  1.3  rillig 	if (flags & FLAG0 && flags & FLAG1)
    314  1.3  rillig 		println("FLAG0 and FLAG1 are both set");
    315  1.3  rillig 
    316  1.3  rillig 	if ((flags & (FLAG0 | FLAG1)) != 0)
    317  1.3  rillig 		println("At least one of FLAG0 and FLAG1 is set");
    318  1.3  rillig 
    319  1.3  rillig 	if (flags & FLAG28)
    320  1.3  rillig 		println("FLAG28 is set");
    321  1.3  rillig }
    322  1.3  rillig 
    323  1.3  rillig /*
    324  1.3  rillig  * In all the above conditions (or controlling expressions, as the C standard
    325  1.3  rillig  * calls them), the result of the operator '&' is compared against 0.  This
    326  1.3  rillig  * makes this pattern work, no matter whether the bits are in the low-value
    327  1.3  rillig  * range or in the high-value range (such as FLAG28, which has the value
    328  1.4  rillig  * 1073741824, which is more than what would fit into an unsigned char).
    329  1.4  rillig  * Even if an enum could be extended to larger types than int, this pattern
    330  1.3  rillig  * would work.
    331  1.3  rillig  */
    332  1.3  rillig 
    333  1.3  rillig /*
    334  1.3  rillig  * There is a crucial difference between a _Bool variable and an ordinary
    335  1.4  rillig  * integer variable.  C99 6.3.1.2 defines a conversion from an arbitrary
    336  1.4  rillig  * scalar value to _Bool as equivalent to (value != 0 ? 1 : 0).  This means
    337  1.4  rillig  * that even if _Bool is implemented as an 8-bit unsigned integer, assigning
    338  1.4  rillig  * 256 to it would still result in the value 1 being stored.  Storing 256 in
    339  1.4  rillig  * an ordinary 8-bit unsigned integer would result in the value 0 being
    340  1.4  rillig  * stored.  See the test d_c99_bool.c for more details.
    341  1.2  rillig  *
    342  1.3  rillig  * Because of this, expressions like (flags & FLAG28) are only allowed in
    343  1.3  rillig  * bool context if they are guaranteed not to be truncated, even if the
    344  1.3  rillig  * result were to be stored in a plain unsigned integer.
    345  1.2  rillig  */
    346  1.3  rillig 
    347  1.4  rillig /*ARGSUSED*/
    348  1.3  rillig void
    349  1.3  rillig SB007_allow_flag_test_on_bit_set_enums(enum Flags flags)
    350  1.3  rillig {
    351  1.3  rillig 	bool b;
    352  1.3  rillig 
    353  1.3  rillig 	/*
    354  1.4  rillig 	 * FLAG0 has the value 1 and thus can be stored in a bool variable
    355  1.4  rillig 	 * without truncation.  Nevertheless this special case is not allowed
    356  1.4  rillig 	 * because it would be too confusing if FLAG0 would work and all the
    357  1.4  rillig 	 * other flags wouldn't.
    358  1.3  rillig 	 */
    359  1.4  rillig 	b = flags & FLAG0;	/* expect: 107 */
    360  1.3  rillig 
    361  1.3  rillig 	/*
    362  1.3  rillig 	 * Assuming that FLAG1 is set in flags, a _Bool variable stores this
    363  1.4  rillig 	 * as 1, as defined by C99 6.3.1.2.  A uint8_t variable would store
    364  1.4  rillig 	 * it as 2, as that is the integer value of FLAG1.  Since FLAG1 fits
    365  1.4  rillig 	 * in a uint8_t, no truncation takes place.
    366  1.3  rillig 	 */
    367  1.4  rillig 	b = flags & FLAG1;	/* expect: 107 */
    368  1.3  rillig 
    369  1.3  rillig 	/*
    370  1.4  rillig 	 * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to
    371  1.4  rillig 	 * zero.  In a uint8_t, the stored value would be 0 since bit 28 is
    372  1.4  rillig 	 * out of range for a uint8_t and thus gets truncated.
    373  1.3  rillig 	 */
    374  1.4  rillig 	b = flags & FLAG28;	/* expect: 107 */
    375  1.3  rillig }
    376  1.3  rillig 
    377  1.3  rillig /* A bool bit field is compatible with bool. Other bit fields are not. */
    378  1.3  rillig 
    379  1.3  rillig struct flags {
    380  1.3  rillig 	bool bool_flag: 1;
    381  1.3  rillig 	unsigned uint_flag: 1;
    382  1.3  rillig };
    383  1.3  rillig 
    384  1.4  rillig /*ARGSUSED*/
    385  1.3  rillig void
    386  1.4  rillig SB008_bit_fields(const struct flags *flags)
    387  1.2  rillig {
    388  1.3  rillig 	bool b;
    389  1.3  rillig 
    390  1.3  rillig 	b = flags->bool_flag;	/* ok */
    391  1.4  rillig 	b = flags->uint_flag;	/* expect: 107 */
    392  1.4  rillig 	flags->bool_flag = b;
    393  1.4  rillig 	flags->uint_flag = b;	/* expect: 107 */
    394  1.3  rillig }
    395  1.3  rillig 
    396  1.3  rillig /* Test implicit conversion when returning a value from a function. */
    397  1.3  rillig 
    398  1.4  rillig /*ARGSUSED*/
    399  1.3  rillig bool
    400  1.3  rillig returning_bool(bool b, int i, const char *p)
    401  1.3  rillig {
    402  1.3  rillig 	if (i > 0)
    403  1.3  rillig 		return b;	/* ok */
    404  1.3  rillig 	if (i < 0)
    405  1.4  rillig 		return i;	/* expect: 211 */
    406  1.4  rillig 	return p;		/* expect: 211 */
    407  1.3  rillig }
    408  1.3  rillig 
    409  1.4  rillig /*ARGSUSED*/
    410  1.3  rillig char
    411  1.3  rillig returning_char(bool b, int i, const char *p)
    412  1.3  rillig {
    413  1.3  rillig 	if (i > 0)
    414  1.4  rillig 		return b;	/* expect: 211 */
    415  1.3  rillig 	if (i < 0)
    416  1.4  rillig 		return i;	/* XXX: narrowing conversion */
    417  1.4  rillig 	return p;		/* expect: 183 */
    418  1.4  rillig }
    419  1.4  rillig 
    420  1.4  rillig bool
    421  1.4  rillig return_constant_false(void)
    422  1.4  rillig {
    423  1.4  rillig 	return 0;
    424  1.4  rillig }
    425  1.4  rillig 
    426  1.4  rillig bool
    427  1.4  rillig return_constant_true(void)
    428  1.4  rillig {
    429  1.4  rillig 	return 1;
    430  1.4  rillig }
    431  1.4  rillig 
    432  1.4  rillig bool
    433  1.4  rillig return_invalid_integer(void)
    434  1.4  rillig {
    435  1.4  rillig 	return 2;		/* expect: 211 */
    436  1.3  rillig }
    437  1.3  rillig 
    438  1.3  rillig /* Test passing arguments to a function. */
    439  1.3  rillig 
    440  1.4  rillig extern void
    441  1.4  rillig taking_arguments(bool, int, const char *, ...);
    442  1.3  rillig 
    443  1.3  rillig void
    444  1.3  rillig passing_arguments(bool b, int i, const char *p)
    445  1.3  rillig {
    446  1.3  rillig 	/* No conversion necessary. */
    447  1.3  rillig 	taking_arguments(b, i, p);
    448  1.3  rillig 
    449  1.3  rillig 	/* Implicitly converting bool to other scalar types. */
    450  1.4  rillig 	taking_arguments(b, b, b);	/* expect: 334, 334 */
    451  1.3  rillig 
    452  1.3  rillig 	/* Implicitly converting int to bool (arg #1). */
    453  1.4  rillig 	taking_arguments(i, i, i);	/* expect: 334, 154 */
    454  1.3  rillig 
    455  1.3  rillig 	/* Implicitly converting pointer to bool (arg #1). */
    456  1.4  rillig 	taking_arguments(p, p, p);	/* expect: 334, 154 */
    457  1.3  rillig 
    458  1.3  rillig 	/* Passing bool as vararg. */
    459  1.4  rillig 	taking_arguments(b, i, p, b, i, p); /* expect: arg#4 */ // TODO
    460  1.4  rillig 
    461  1.4  rillig 	/* Passing a bool constant. */
    462  1.4  rillig 	taking_arguments(0, i, p);
    463  1.4  rillig 
    464  1.4  rillig 	/* Passing a bool constant. */
    465  1.4  rillig 	taking_arguments(1, i, p);
    466  1.4  rillig 
    467  1.4  rillig 	/* Trying to pass an invalid integer. */
    468  1.4  rillig 	taking_arguments(2, i, p);	/* expect: 334 */
    469  1.4  rillig }
    470  1.4  rillig 
    471  1.4  rillig /*
    472  1.4  rillig  * This is just normal access to a bool member of a struct, to ensure that
    473  1.4  rillig  * these produce no errors.
    474  1.4  rillig  */
    475  1.4  rillig void
    476  1.4  rillig struct_access_operators(void)
    477  1.4  rillig {
    478  1.4  rillig 	struct bool_struct {
    479  1.4  rillig 		bool b;
    480  1.4  rillig 	};
    481  1.4  rillig 
    482  1.4  rillig 	/* Initialize and assign using boolean constants. */
    483  1.4  rillig 	bool b = 0;
    484  1.4  rillig 	b = 1;
    485  1.4  rillig 
    486  1.4  rillig 	/* Access a struct member using the '.' operator. */
    487  1.4  rillig 	struct bool_struct bs = { 1 };
    488  1.4  rillig 	b = bs.b;
    489  1.4  rillig 	bs.b = b;
    490  1.4  rillig 	bs.b = 0;
    491  1.4  rillig 
    492  1.4  rillig 	/* Access a struct member using the '->' operator. */
    493  1.4  rillig 	struct bool_struct *bsp = &bs;
    494  1.4  rillig 	b = bsp->b;
    495  1.4  rillig 	bsp->b = b;
    496  1.4  rillig 	bsp->b = 0;
    497  1.4  rillig 
    498  1.4  rillig 	/* Taking the address of a bool lvalue. */
    499  1.4  rillig 	bool *bp;
    500  1.4  rillig 	bp = &b;
    501  1.4  rillig 	*bp = b;
    502  1.4  rillig 	b = *bp;
    503  1.4  rillig }
    504  1.4  rillig 
    505  1.4  rillig /*
    506  1.4  rillig  * Comparing a _Bool expression to 0 or 1 is redundant.  It may come from
    507  1.4  rillig  * an earlier version of the code, before it got migrated to using _Bool.
    508  1.4  rillig  * Usually, bool expressions are used directly as control expressions or
    509  1.4  rillig  * as argument to the boolean operators such as '!', '&&', '||'.
    510  1.4  rillig  *
    511  1.4  rillig  * Since lint steps in after the C preprocessor, it has no chance of seeing
    512  1.4  rillig  * the original source code, which may well have been "b == false" instead
    513  1.4  rillig  * of "b == 0".
    514  1.4  rillig  */
    515  1.4  rillig bool
    516  1.4  rillig compare_var_with_constant(bool b)
    517  1.4  rillig {
    518  1.4  rillig 	bool t1 = b == 0;
    519  1.4  rillig 	bool t2 = t1 != 0;
    520  1.4  rillig 	bool t3 = t2 == 1;
    521  1.4  rillig 	bool t4 = t3 != 1;
    522  1.4  rillig 	return t4 ^ t3;
    523  1.2  rillig }
    524  1.5  rillig 
    525  1.5  rillig bool
    526  1.6  rillig SB003_operand_comma(bool b, int i)
    527  1.5  rillig {
    528  1.6  rillig 	b = (b, !b);
    529  1.6  rillig 	i = (i, i + 1);
    530  1.5  rillig 	return b;
    531  1.5  rillig }
    532  1.7  rillig 
    533  1.7  rillig void
    534  1.7  rillig bit_field_as_operator_argument(void)
    535  1.7  rillig {
    536  1.7  rillig 	struct s {
    537  1.7  rillig 		bool ordinary;
    538  1.7  rillig 		bool bit_field: 1;
    539  1.7  rillig 	};
    540  1.7  rillig 
    541  1.7  rillig 	struct s s = { 0 };
    542  1.7  rillig 
    543  1.7  rillig 	s.ordinary = s.ordinary | s.ordinary;
    544  1.7  rillig 	s.bit_field = s.bit_field | s.bit_field; /* FIXME *//* expect: 107 */
    545  1.7  rillig }
    546