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