Home | History | Annotate | Line # | Download | only in lint1
d_c99_bool_strict.c revision 1.3
      1  1.3  rillig /*	$NetBSD: d_c99_bool_strict.c,v 1.3 2021/01/11 00:28:28 rillig Exp $	*/
      2  1.1  rillig # 3 "d_c99_bool_strict.c"
      3  1.1  rillig 
      4  1.1  rillig /*
      5  1.1  rillig  * Experimental feature:  allow to treat _Bool as incompatible with all
      6  1.1  rillig  * scalar types.  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.1  rillig  * SB006: A constant integer expression is compatible with type _Bool if
     22  1.1  rillig  * it is an integer constant with value 0 or 1, or if the result type of
     23  1.1  rillig  * its main operator is _Bool.
     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.2  rillig // Not yet implemented: /* 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.1  rillig 	if (/*CONSTCOND*/2)
     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.1  rillig 	if (i)
     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.1  rillig 	if (d)
     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.1  rillig 	if (p)
     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.1  rillig SB002_operator_result(bool b)
     92  1.1  rillig {
     93  1.1  rillig 	b = b;
     94  1.1  rillig 	char c = b;
     95  1.1  rillig 	int i = b;
     96  1.1  rillig 	double d = b;
     97  1.1  rillig 	void *p = b;
     98  1.1  rillig 
     99  1.1  rillig 	/* 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.1  rillig 	 * These assignments are not ok, they implicitly convert from bool
    112  1.1  rillig 	 * to int.
    113  1.1  rillig 	 */
    114  1.1  rillig 	i = !b;
    115  1.1  rillig 	i = i == i;
    116  1.1  rillig 	i = i != i;
    117  1.1  rillig 	i = i < i;
    118  1.1  rillig 	i = i <= i;
    119  1.1  rillig 	i = i >= i;
    120  1.1  rillig 	i = i > i;
    121  1.1  rillig 	i = b && b;
    122  1.1  rillig 	i = b || b;
    123  1.1  rillig }
    124  1.1  rillig 
    125  1.1  rillig void
    126  1.1  rillig SB003_operands(bool b, int i)
    127  1.1  rillig {
    128  1.1  rillig 
    129  1.1  rillig 	/* 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.1  rillig 	/* These assignments implicitly convert from scalar to bool. */
    135  1.1  rillig 	b = !i;
    136  1.1  rillig 	b = i && i;
    137  1.1  rillig 	b = i || i;
    138  1.1  rillig }
    139  1.1  rillig 
    140  1.1  rillig void
    141  1.1  rillig SB004_non_bool_operands(bool b, unsigned u)
    142  1.1  rillig {
    143  1.1  rillig 	b = !b;			/* ok */
    144  1.1  rillig 	b = ~b;			/* not ok */
    145  1.1  rillig 	++b;			/* not ok */
    146  1.1  rillig 	--b;			/* not ok */
    147  1.1  rillig 	b++;			/* not ok */
    148  1.1  rillig 	b--;			/* not ok */
    149  1.1  rillig 	b = +b;			/* not ok */
    150  1.1  rillig 	b = -b;			/* not ok */
    151  1.1  rillig 
    152  1.1  rillig 	b = b * b;		/* not ok */
    153  1.1  rillig 	b = b / b;		/* not ok */
    154  1.1  rillig 	b = b % b;		/* not ok */
    155  1.1  rillig 	b = b + b;		/* not ok */
    156  1.1  rillig 	b = b - b;		/* not ok */
    157  1.1  rillig 	b = b << b;		/* not ok */
    158  1.1  rillig 	b = b >> b;		/* not ok */
    159  1.1  rillig 
    160  1.1  rillig 	b = b < b;		/* not ok */
    161  1.1  rillig 	b = b <= b;		/* not ok */
    162  1.1  rillig 	b = b > b;		/* not ok */
    163  1.1  rillig 	b = b >= b;		/* not ok */
    164  1.1  rillig 	b = b == b;		/* ok */
    165  1.1  rillig 	b = b != b;		/* ok */
    166  1.1  rillig 
    167  1.1  rillig 	b = b & b;		/* ok */
    168  1.1  rillig 	b = b ^ b;		/* ok */
    169  1.1  rillig 	b = b | b;		/* ok */
    170  1.1  rillig 	b = b && b;		/* ok */
    171  1.1  rillig 	b = b || b;		/* ok */
    172  1.1  rillig 	b = b ? b : b;		/* ok */
    173  1.1  rillig 
    174  1.1  rillig 	b = b;			/* ok */
    175  1.1  rillig 	b *= b;			/* not ok */
    176  1.1  rillig 	b /= b;			/* not ok */
    177  1.1  rillig 	b %= b;			/* not ok */
    178  1.1  rillig 	b += b;			/* not ok */
    179  1.1  rillig 	b -= b;			/* not ok */
    180  1.1  rillig 	b <<= b;		/* not ok */
    181  1.1  rillig 	b >>= b;		/* not ok */
    182  1.1  rillig 	b &= b;			/* ok */
    183  1.1  rillig 	b ^= b;			/* ok */
    184  1.1  rillig 	b |= b;			/* ok */
    185  1.1  rillig 
    186  1.1  rillig 	/* Operations with mixed types. */
    187  1.1  rillig 	u = b * u;		/* not ok */
    188  1.1  rillig 	u = u * b;		/* not ok */
    189  1.1  rillig 	u = b / u;		/* not ok */
    190  1.1  rillig 	u = u / b;		/* not ok */
    191  1.1  rillig 	u = b % u;		/* not ok */
    192  1.1  rillig 	u = u % b;		/* not ok */
    193  1.1  rillig 	u = b + u;		/* not ok */
    194  1.1  rillig 	u = u + b;		/* not ok */
    195  1.1  rillig 	u = b - u;		/* not ok */
    196  1.1  rillig 	u = u - b;		/* not ok */
    197  1.1  rillig 	u = b << u;		/* not ok */
    198  1.1  rillig 	u = u << b;		/* not ok */
    199  1.1  rillig 	u = b >> u;		/* not ok */
    200  1.1  rillig 	u = u >> b;		/* not ok */
    201  1.1  rillig 	u = b ? u : u;		/* ok */
    202  1.1  rillig 	u = b ? b : u;		/* not ok */
    203  1.1  rillig 	u = b ? u : b;		/* not ok */
    204  1.1  rillig }
    205  1.1  rillig 
    206  1.1  rillig void
    207  1.1  rillig SB005_convert_from_bool_to_scalar(bool b)
    208  1.1  rillig {
    209  1.1  rillig 	int i;
    210  1.1  rillig 	unsigned u;
    211  1.1  rillig 	double d;
    212  1.1  rillig 	void *p;
    213  1.1  rillig 
    214  1.1  rillig 	i = b;			/* not ok */
    215  1.1  rillig 	u = b;			/* not ok */
    216  1.1  rillig 	d = b;			/* not ok */
    217  1.1  rillig 	p = b;			/* not ok */
    218  1.1  rillig }
    219  1.1  rillig 
    220  1.1  rillig enum SB006_bool_constant_expression {
    221  1.1  rillig 	/* Ok: 0 is a boolean constant expression. */
    222  1.1  rillig 	INT0 = 0 ? 100 : 101,
    223  1.1  rillig 
    224  1.1  rillig 	/* Ok: 1 is a boolean constant expression. */
    225  1.1  rillig 	INT1 = 1 ? 100 : 101,
    226  1.1  rillig 
    227  1.1  rillig 	/* Not ok: 2 is not a boolean constant (neither 0 nor 1). */
    228  1.1  rillig 	INT2 = 2 ? 100 : 101,
    229  1.1  rillig 
    230  1.1  rillig 	/*
    231  1.1  rillig 	 * Not ok: the intermediate expression "2 - 2" has return type
    232  1.1  rillig 	 * scalar, not bool.  It is irrelevant that the final result
    233  1.1  rillig 	 * is 0, which would be a boolean constant.
    234  1.1  rillig 	 */
    235  1.1  rillig 	ARITH = (2 - 2) ? 100 : 101,
    236  1.1  rillig 
    237  1.1  rillig 	/*
    238  1.1  rillig 	 * Ok: The 13 and 12 are not boolean expressions, but they
    239  1.1  rillig 	 * are not in the calculation path that leads to the final
    240  1.1  rillig 	 * result.  The important point is that the operator '>' has
    241  1.1  rillig 	 * return type bool.
    242  1.1  rillig 	 */
    243  1.1  rillig 	Q1 = (13 > 12) ? 100 : 101,
    244  1.1  rillig 
    245  1.1  rillig 	/*
    246  1.1  rillig 	 * Not ok: The 7 is irrelevant for the final result of the
    247  1.1  rillig 	 * expression, yet it turns the result type of the operator
    248  1.1  rillig 	 * '?:' to be int, not bool.
    249  1.1  rillig 	 */
    250  1.1  rillig 	Q2 = (13 > 12 ? 1 : 7) ? 100 : 101,
    251  1.1  rillig 
    252  1.1  rillig 	BINAND = 0 & 1,		/* ok */
    253  1.1  rillig 
    254  1.1  rillig 	BINXOR = 0 ^ 1,		/* ok */
    255  1.1  rillig 
    256  1.1  rillig 	BINOR = 0 | 1,		/* ok */
    257  1.1  rillig 
    258  1.1  rillig 	LOGOR = 0 || 1,		/* ok */
    259  1.1  rillig 
    260  1.1  rillig 	LOGAND = 0 && 1,	/* ok */
    261  1.1  rillig };
    262  1.2  rillig 
    263  1.3  rillig /*
    264  1.3  rillig  * An efficient implementation technique for a collection of boolean flags
    265  1.3  rillig  * is an enum.  The enum declaration groups the available constants, and as
    266  1.3  rillig  * of 2020, compilers such as GCC and Clang have basic support for detecting
    267  1.3  rillig  * type mismatches on enums.
    268  1.3  rillig  */
    269  1.3  rillig 
    270  1.3  rillig enum Flags {
    271  1.3  rillig 	FLAG0 = 1 << 0,
    272  1.3  rillig 	FLAG1 = 1 << 1,
    273  1.3  rillig 	FLAG28 = 1 << 28
    274  1.2  rillig };
    275  1.2  rillig 
    276  1.2  rillig /*
    277  1.3  rillig  * The usual way to query one of the flags is demonstrated below.
    278  1.3  rillig  */
    279  1.3  rillig 
    280  1.3  rillig extern void println(const char *);
    281  1.3  rillig 
    282  1.3  rillig void
    283  1.3  rillig query_flag_from_enum_bit_set(enum Flags flags)
    284  1.3  rillig {
    285  1.3  rillig 
    286  1.3  rillig 	if (flags & FLAG0)
    287  1.3  rillig 		println("FLAG0 is set");
    288  1.3  rillig 
    289  1.3  rillig 	if ((flags & FLAG1) != 0)
    290  1.3  rillig 		println("FLAG1 is set");
    291  1.3  rillig 
    292  1.3  rillig 	if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1))
    293  1.3  rillig 		println("FLAG0 and FLAG1 are both set");
    294  1.3  rillig 	if (flags & FLAG0 && flags & FLAG1)
    295  1.3  rillig 		println("FLAG0 and FLAG1 are both set");
    296  1.3  rillig 
    297  1.3  rillig 	if ((flags & (FLAG0 | FLAG1)) != 0)
    298  1.3  rillig 		println("At least one of FLAG0 and FLAG1 is set");
    299  1.3  rillig 
    300  1.3  rillig 	if (flags & FLAG28)
    301  1.3  rillig 		println("FLAG28 is set");
    302  1.3  rillig }
    303  1.3  rillig 
    304  1.3  rillig /*
    305  1.3  rillig  * In all the above conditions (or controlling expressions, as the C standard
    306  1.3  rillig  * calls them), the result of the operator '&' is compared against 0.  This
    307  1.3  rillig  * makes this pattern work, no matter whether the bits are in the low-value
    308  1.3  rillig  * range or in the high-value range (such as FLAG28, which has the value
    309  1.3  rillig  * 1073741824, which is more than what fits into an unsigned char).  Even
    310  1.3  rillig  * if an enum could be extended to larger types than int, this pattern
    311  1.3  rillig  * would work.
    312  1.3  rillig  */
    313  1.3  rillig 
    314  1.3  rillig /*
    315  1.3  rillig  * There is a crucial difference between a _Bool variable and an ordinary
    316  1.3  rillig  * integer variable though.  C99 6.3.1.2 defines a conversion from an
    317  1.3  rillig  * arbitrary scalar type to _Bool as (value != 0 ? 1 : 0).  This means that
    318  1.3  rillig  * even if _Bool is implemented as an 8-bit unsigned integer, assigning 256
    319  1.3  rillig  * to it would still result in the value 1 being stored.  Storing 256 in an
    320  1.3  rillig  * ordinary 8-bit unsigned integer would result in the value 0 being stored.
    321  1.3  rillig  * See the test d_c99_bool.c for more details.
    322  1.2  rillig  *
    323  1.3  rillig  * Because of this, expressions like (flags & FLAG28) are only allowed in
    324  1.3  rillig  * bool context if they are guaranteed not to be truncated, even if the
    325  1.3  rillig  * result were to be stored in a plain unsigned integer.
    326  1.2  rillig  */
    327  1.3  rillig 
    328  1.3  rillig void
    329  1.3  rillig SB007_allow_flag_test_on_bit_set_enums(enum Flags flags)
    330  1.3  rillig {
    331  1.3  rillig 	bool b;
    332  1.3  rillig 
    333  1.3  rillig 	/*
    334  1.3  rillig 	 * FLAG0 has the value 1 and can therefore be stored in a bool
    335  1.3  rillig 	 * variable without truncation.  Nevertheless this special case
    336  1.3  rillig 	 * is not allowed because it would be too confusing if FLAG0 would
    337  1.3  rillig 	 * work and all the other flags wouldn't.
    338  1.3  rillig 	 */
    339  1.3  rillig 	b = flags & FLAG0;
    340  1.3  rillig 
    341  1.3  rillig 	/*
    342  1.3  rillig 	 * Assuming that FLAG1 is set in flags, a _Bool variable stores this
    343  1.3  rillig 	 * as 1, as defined by C99 6.3.1.2.  An unsigned char variable would
    344  1.3  rillig 	 * store it as 2, as that is the integer value of FLAG1.  Since FLAG1
    345  1.3  rillig 	 * fits in an unsigned char, no truncation takes place.
    346  1.3  rillig 	 */
    347  1.3  rillig 	b = flags & FLAG1;
    348  1.3  rillig 
    349  1.3  rillig 	/*
    350  1.3  rillig 	 * In a _Bool variable, FLAG28 is stored as 1, as above.  In an
    351  1.3  rillig 	 * unsigned char, the stored value would be 0 since bit 28 is out of
    352  1.3  rillig 	 * range for an unsigned char, which usually has 8 significant bits.
    353  1.3  rillig 	 */
    354  1.3  rillig 	b = flags & FLAG28;
    355  1.3  rillig }
    356  1.3  rillig 
    357  1.3  rillig /* A bool bit field is compatible with bool. Other bit fields are not. */
    358  1.3  rillig 
    359  1.3  rillig struct flags {
    360  1.3  rillig 	bool bool_flag: 1;
    361  1.3  rillig 	unsigned uint_flag: 1;
    362  1.3  rillig };
    363  1.3  rillig 
    364  1.3  rillig void
    365  1.3  rillig SB008_flags_from_bit_fields(const struct flags *flags)
    366  1.2  rillig {
    367  1.3  rillig 	bool b;
    368  1.3  rillig 
    369  1.3  rillig 	b = flags->bool_flag;	/* ok */
    370  1.3  rillig 	b = flags->uint_flag;	/* not ok */
    371  1.3  rillig }
    372  1.3  rillig 
    373  1.3  rillig /* Test implicit conversion when returning a value from a function. */
    374  1.3  rillig 
    375  1.3  rillig bool
    376  1.3  rillig returning_bool(bool b, int i, const char *p)
    377  1.3  rillig {
    378  1.3  rillig 	if (i > 0)
    379  1.3  rillig 		return b;	/* ok */
    380  1.3  rillig 	if (i < 0)
    381  1.3  rillig 		return i;	/* not ok */
    382  1.3  rillig 	return p;		/* not ok */
    383  1.3  rillig }
    384  1.3  rillig 
    385  1.3  rillig char
    386  1.3  rillig returning_char(bool b, int i, const char *p)
    387  1.3  rillig {
    388  1.3  rillig 	if (i > 0)
    389  1.3  rillig 		return b;	/* not ok */
    390  1.3  rillig 	if (i < 0)
    391  1.3  rillig 		return i;	/* not ok, but not related to bool */
    392  1.3  rillig 	return p;		/* not ok */
    393  1.3  rillig }
    394  1.3  rillig 
    395  1.3  rillig /* Test passing arguments to a function. */
    396  1.3  rillig 
    397  1.3  rillig extern void taking_arguments(bool, int, const char *, ...);
    398  1.3  rillig 
    399  1.3  rillig void
    400  1.3  rillig passing_arguments(bool b, int i, const char *p)
    401  1.3  rillig {
    402  1.3  rillig 	/* No conversion necessary. */
    403  1.3  rillig 	taking_arguments(b, i, p);
    404  1.3  rillig 
    405  1.3  rillig 	/* Implicitly converting bool to other scalar types. */
    406  1.3  rillig 	taking_arguments(b, b, b);
    407  1.3  rillig 
    408  1.3  rillig 	/* Implicitly converting int to bool (arg #1). */
    409  1.3  rillig 	taking_arguments(i, i, i);
    410  1.3  rillig 
    411  1.3  rillig 	/* Implicitly converting pointer to bool (arg #1). */
    412  1.3  rillig 	taking_arguments(p, p, p);
    413  1.3  rillig 
    414  1.3  rillig 	/* Passing bool as vararg. */
    415  1.3  rillig 	taking_arguments(b, i, p, b, i, p);
    416  1.2  rillig }
    417