1 /* $NetBSD: d_c99_bool_strict.c,v 1.56 2025/07/07 19:57:17 rillig Exp $ */ 2 # 3 "d_c99_bool_strict.c" 3 4 /* 5 * The option -T treats _Bool as incompatible with all other scalar types. 6 * This is implemented by the following rules: 7 * 8 * strict-bool-typedef: 9 * The type _Bool is compatible with any typedef of _Bool. 10 * 11 * Note: Since <stdbool.h> defines bool as textual alias of _Bool, 12 * having another typedef for bool is unusual. 13 * 14 * strict-bool-constant: 15 * There are 2 bool constants named false and true. 16 * No other constants are compatible with type _Bool. 17 * 18 * Note: Internally these constants are named __lint_false and 19 * __lint_true. 20 * 21 * strict-bool-bit-field: 22 * A struct or union member that is a bit field with underlying type 23 * bool is compatible with plain bool. 24 * 25 * strict-bool-conversion: 26 * There is no implicit conversion between _Bool and any other type. 27 * 28 * strict-bool-controlling-expression: 29 * Controlling expressions in 'if', 'while', 'for', '?:' must be of 30 * type bool, except for a literal 0 in a do-while loop. 31 * 32 * strict-bool-operand-unary: 33 * Operator bool? scalar? 34 * ! yes - 35 * & yes yes 36 * The other unary operators do not accept bool operands. 37 * 38 * strict-bool-operand-binary: 39 * Operator left: bool? other? right: bool? other? 40 * . - yes yes yes 41 * -> - yes yes yes 42 * <=, <, >=, > - yes - yes 43 * ==, != yes yes yes yes 44 * & yes yes yes yes 45 * ^ yes yes yes yes 46 * | yes yes yes yes 47 * && yes - yes - 48 * || yes - yes - 49 * ? yes - yes yes 50 * : yes yes yes yes 51 * = yes yes yes yes 52 * &=, ^=, |= yes yes yes yes 53 * , yes yes yes yes 54 * The other binary operators do not accept bool operands. 55 * 56 * strict-bool-operator-result: 57 * The result type of the operators '!', '<', '<=', '>', '>=', 58 * '==', '!=', '&&', '||' is _Bool instead of int. 59 * 60 * strict-bool-bitwise-and: 61 * Expressions of the form "flags & FLAG" are compatible with _Bool if 62 * the resulting value is used in a context where it is implicitly and 63 * immediately compared to zero. 64 * 65 * Note: Examples for such contexts are controlling expressions or the 66 * operands of the operators '!', '&&', '||'. 67 * 68 * Note: Counterexamples for contexts are assignments to a bool variable, 69 * as without the conversion from C99 6.3.1.2, converting an integer to a 70 * "bool-like" integer type truncated the value instead of comparing it 71 * to 0. 72 * 73 * Note: These rules ensure that conforming code behaves the same in both 74 * C99 and in environments that emulate a boolean type using a small 75 * integer type. 76 */ 77 78 /* 79 * The header <stdbool.h> defines the macros bool = _Bool, false = 0 and 80 * true = 1. Without further hacks, this would mean that constant expressions 81 * of integer type have to be regarded as possible boolean constants if their 82 * value is either 0 or 1. 83 * 84 * This would not help in migrating old code to use bool consistently. 85 * Therefore lint provides its own <stdbool.h> header that expands false to 86 * __lint_false and true to __lint_true, two predefined constant expressions. 87 */ 88 89 /* lint1-extra-flags: -hT -X 351 */ 90 91 /* 92 * strict-bool-typedef 93 */ 94 95 /* 96 * Using a typedef for bool does not hurt the checks, they all use the 97 * underlying basic type (see tspec_t), which is BOOL. 98 */ 99 typedef _Bool bool; 100 101 extern void accept_bool(bool); 102 extern void println(const char *); 103 extern void take_arguments(bool, int, const char *, ...); 104 extern void do_nothing(void); 105 106 /* 107 * strict-bool-constant 108 */ 109 110 void 111 strict_bool_constant(void) 112 { 113 accept_bool(__lint_false); 114 accept_bool(__lint_true); 115 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 116 accept_bool(0); 117 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 118 accept_bool(1); 119 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 120 accept_bool(2); 121 } 122 123 enum strict_bool_constant_expressions { 124 /* Ok: __lint_false is a boolean constant expression. */ 125 FALSE = __lint_false ? 100 : 101, 126 127 /* Ok: __lint_true is a boolean constant expression. */ 128 TRUE = __lint_true ? 100 : 101, 129 130 /* Not ok: an integer is not a boolean constant expression. */ 131 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 132 INT0 = 0 ? 100 : 101, 133 134 /* Not ok: an integer is not a boolean constant expression. */ 135 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 136 INT1 = 1 ? 100 : 101, 137 138 /* Not ok: 2 is not a boolean constant. */ 139 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 140 INT2 = 2 ? 100 : 101, 141 142 /* Not ok: compound integer expressions are not bool. */ 143 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 144 ARITH = (2 - 2) ? 100 : 101, 145 146 /* 147 * Without strict bool mode, these two variants of an expression can 148 * occur when a preprocessor macro is either defined to 1 or left 149 * empty (since C99). 150 * 151 * In strict bool mode, the resulting expression can be compared 152 * against 0 to achieve the same effect (so +0 != 0 or 1 + 0 != 0). 153 */ 154 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 155 BINARY_PLUS = (1 + 0) ? 100 : 101, 156 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 157 UNARY_PLUS = (+0) ? 100 : 101, 158 159 /* The main operator '>' has return type bool. */ 160 Q1 = (13 > 12) ? 100 : 101, 161 162 /* 163 * The parenthesized expression has type int and thus cannot be 164 * used as the controlling expression in the '?:' operator. 165 */ 166 /* expect+1: error: left operand of '?' must be bool, not 'int' [331] */ 167 Q2 = (13 > 12 ? 1 : 7) ? 100 : 101, 168 169 /* expect+1: error: integral constant expression expected [55] */ 170 BINAND_BOOL = __lint_false & __lint_true, 171 BINAND_INT = 0 & 1, 172 173 /* expect+1: error: integral constant expression expected [55] */ 174 BINXOR_BOOL = __lint_false ^ __lint_true, 175 BINXOR_INT = 0 ^ 1, 176 177 /* expect+1: error: integral constant expression expected [55] */ 178 BINOR_BOOL = __lint_false | __lint_true, 179 BINOR_INT = 0 | 1, 180 181 /* expect+1: error: integral constant expression expected [55] */ 182 LOGOR_BOOL = __lint_false || __lint_true, 183 /* expect+2: error: left operand of '||' must be bool, not 'int' [331] */ 184 /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */ 185 LOGOR_INT = 0 || 1, 186 187 /* expect+1: error: integral constant expression expected [55] */ 188 LOGAND_BOOL = __lint_false && __lint_true, 189 /* expect+2: error: left operand of '&&' must be bool, not 'int' [331] */ 190 /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */ 191 LOGAND_INT = 0 && 1, 192 }; 193 194 /* 195 * strict-bool-bit-fields 196 */ 197 198 void 199 strict_bool_bit_fields(void) 200 { 201 struct flags { 202 bool bool_flag: 1; 203 unsigned uint_flag: 1; 204 }; 205 206 struct flags flags = { __lint_false, 0 }; 207 struct flags *flags_ptr = &flags; 208 bool b; 209 210 b = flags.bool_flag; 211 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'unsigned int' [107] */ 212 b = flags.uint_flag; 213 flags.bool_flag = b; 214 /* expect+1: error: operands of '=' have incompatible types 'unsigned int' and '_Bool' [107] */ 215 flags.uint_flag = b; 216 217 b = flags_ptr->bool_flag; 218 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'unsigned int' [107] */ 219 b = flags_ptr->uint_flag; 220 flags_ptr->bool_flag = b; 221 /* expect+1: error: operands of '=' have incompatible types 'unsigned int' and '_Bool' [107] */ 222 flags_ptr->uint_flag = b; 223 } 224 225 void 226 strict_bool_bit_fields_operand_conversion(void) 227 { 228 struct s { 229 bool ordinary; 230 bool bit_field: 1; 231 }; 232 233 struct s s = { 0 > 0 }; 234 235 s.ordinary = s.ordinary | s.ordinary; 236 s.bit_field = s.bit_field | s.bit_field; 237 } 238 239 /* 240 * strict-bool-conversion 241 */ 242 243 bool 244 strict_bool_conversion_return_false(void) 245 { 246 return __lint_false; 247 } 248 249 bool 250 strict_bool_conversion_return_true(void) 251 { 252 return __lint_true; 253 } 254 255 bool 256 strict_bool_conversion_return_bool(bool b) 257 { 258 return b; 259 } 260 261 bool 262 strict_bool_conversion_return_0(void) 263 { 264 /* expect+1: error: function has return type '_Bool' but returns 'int' [211] */ 265 return 0; 266 } 267 268 bool 269 strict_bool_conversion_return_1(void) 270 { 271 /* expect+1: error: function has return type '_Bool' but returns 'int' [211] */ 272 return 1; 273 } 274 275 bool 276 strict_bool_conversion_return_2(void) 277 { 278 /* expect+1: error: function has return type '_Bool' but returns 'int' [211] */ 279 return 2; 280 } 281 282 /* expect+2: warning: parameter 'p' unused in function 'strict_bool_conversion_return_pointer' [231] */ 283 bool 284 strict_bool_conversion_return_pointer(const void *p) 285 { 286 /* expect+1: error: function has return type '_Bool' but returns 'pointer' [211] */ 287 return p; 288 } 289 290 char 291 strict_bool_conversion_return_false_as_char(void) 292 { 293 /* expect+1: error: function has return type 'char' but returns '_Bool' [211] */ 294 return __lint_false; 295 } 296 297 char 298 strict_bool_conversion_return_true_as_char(void) 299 { 300 /* expect+1: error: function has return type 'char' but returns '_Bool' [211] */ 301 return __lint_true; 302 } 303 304 305 void 306 strict_bool_conversion_function_argument(void) 307 { 308 accept_bool(__lint_false); 309 accept_bool(__lint_true); 310 } 311 312 void 313 strict_bool_conversion_function_argument_pass(bool b, int i, const char *p) 314 { 315 /* No conversion necessary. */ 316 take_arguments(b, i, p); 317 318 /* Implicitly converting bool to other scalar types. */ 319 /* expect+2: error: parameter 2 expects 'int', gets passed '_Bool' [334] */ 320 /* expect+1: error: parameter 3 expects 'pointer', gets passed '_Bool' [334] */ 321 take_arguments(b, b, b); 322 323 /* Implicitly converting int to bool (arg #1). */ 324 /* expect+2: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 325 /* expect+1: warning: invalid combination of pointer 'pointer to const char' and integer 'int', arg #3 [154] */ 326 take_arguments(i, i, i); 327 328 /* Implicitly converting pointer to bool (arg #1). */ 329 /* expect+2: error: parameter 1 expects '_Bool', gets passed 'pointer' [334] */ 330 /* expect+1: warning: invalid combination of integer 'int' and pointer 'pointer to const char', arg #2 [154] */ 331 take_arguments(p, p, p); 332 333 /* Passing bool as vararg. */ 334 /* TODO: maybe expect+1: arg#4 should not be bool but scalar */ 335 take_arguments(b, i, p, b, i, p); 336 337 /* Passing a bool constant. */ 338 take_arguments(__lint_false, i, p); 339 340 /* Passing a bool constant. */ 341 take_arguments(__lint_true, i, p); 342 343 /* Trying to pass integer constants. */ 344 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 345 take_arguments(0, i, p); 346 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 347 take_arguments(1, i, p); 348 /* expect+1: error: parameter 1 expects '_Bool', gets passed 'int' [334] */ 349 take_arguments(2, i, p); 350 } 351 352 void 353 strict_bool_conversion_between_bool_and_int(void) 354 { 355 bool b; 356 int i; 357 358 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 359 b = 0; 360 b = __lint_false; 361 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 362 b = 1; 363 b = __lint_true; 364 365 i = 0; 366 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 367 i = __lint_false; 368 i = 1; 369 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 370 i = __lint_true; 371 372 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 373 i = b; 374 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 375 b = i; 376 } 377 378 /* expect+2: warning: parameter 'b' unused in function 'strict_bool_conversion_from_bool_to_scalar' [231] */ 379 void 380 strict_bool_conversion_from_bool_to_scalar(bool b) 381 { 382 int i; 383 unsigned u; 384 double d; 385 void *p; 386 387 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 388 i = b; 389 /* expect+1: error: operands of '=' have incompatible types 'unsigned int' and '_Bool' [107] */ 390 u = b; 391 /* expect+1: error: operands of '=' have incompatible types 'double' and '_Bool' [107] */ 392 d = b; 393 /* expect+1: error: operands of '=' have incompatible types 'pointer' and '_Bool' [107] */ 394 p = b; 395 } 396 397 /* 398 * strict-bool-controlling-expression 399 */ 400 401 void 402 strict_bool_controlling_expression(bool b, int i, double d, const void *p) 403 { 404 if (__lint_false) 405 /* expect+1: warning: 'call' statement not reached [193] */ 406 do_nothing(); 407 408 if (__lint_true) 409 do_nothing(); 410 411 if (b) 412 do_nothing(); 413 414 /* expect+1: error: controlling expression must be bool, not 'int' [333] */ 415 if (0) 416 /* expect+1: warning: 'call' statement not reached [193] */ 417 do_nothing(); 418 419 /* expect+1: error: controlling expression must be bool, not 'int' [333] */ 420 if (1) 421 do_nothing(); 422 423 /* expect+1: error: controlling expression must be bool, not 'int' [333] */ 424 if (2) 425 do_nothing(); 426 427 /* Not allowed: There is no implicit conversion from scalar to bool. */ 428 /* expect+1: error: controlling expression must be bool, not 'int' [333] */ 429 if (i) 430 do_nothing(); 431 if (i != 0) 432 do_nothing(); 433 434 /* Not allowed: There is no implicit conversion from scalar to bool. */ 435 /* expect+1: error: controlling expression must be bool, not 'double' [333] */ 436 if (d) 437 do_nothing(); 438 if (d != 0.0) 439 do_nothing(); 440 441 /* Not allowed: There is no implicit conversion from scalar to bool. */ 442 /* expect+1: error: controlling expression must be bool, not 'pointer' [333] */ 443 if (p) 444 do_nothing(); 445 if (p != (void *)0) 446 do_nothing(); 447 448 // An endless loop. The preferred form is 'for (;;)' instead. 449 do { 450 } while (__lint_true); 451 452 // A do-once "loop", often used in statement macros. 453 do { 454 } while (__lint_false); 455 456 // This form is too unusual to be allowed in strict bool mode. 457 do { 458 /* expect+1: error: controlling expression must be bool, not 'int' [333] */ 459 } while (1); 460 461 // Even though 0 is an integer instead of a bool, this idiom is so 462 // common that it is frequently used in system headers. Since the 463 // Clang preprocessor does not mark each token as coming from a system 464 // header or from user code, this idiom can only be allowed everywhere 465 // or nowhere. 466 do { 467 } while (0); 468 } 469 470 /* 471 * strict-bool-operand-unary 472 */ 473 474 void 475 strict_bool_operand_unary_not(void) 476 { 477 bool b = __lint_false; 478 479 b = !b; 480 b = !!!b; 481 b = !__lint_false; 482 b = !__lint_true; 483 484 int i = 0; 485 486 /* expect+1: error: operand of '!' must be bool, not 'int' [330] */ 487 i = !i; 488 /* expect+1: error: operand of '!' must be bool, not 'int' [330] */ 489 i = !!!i; 490 /* expect+1: error: operand of '!' must be bool, not 'int' [330] */ 491 i = !0; 492 /* expect+1: error: operand of '!' must be bool, not 'int' [330] */ 493 i = !1; 494 } 495 496 void 497 strict_bool_operand_unary_address(void) 498 { 499 bool b = __lint_false; 500 501 /* Taking the address of a bool lvalue. */ 502 bool *bp; 503 bp = &b; 504 *bp = b; 505 b = *bp; 506 } 507 508 /* see strict_bool_operand_unary_all below for the other unary operators. */ 509 510 /* 511 * strict-bool-operand-binary 512 */ 513 514 /* 515 * Ensure that bool members can be accessed as usual. 516 */ 517 void 518 strict_bool_operand_binary_dot_arrow(void) 519 { 520 struct bool_struct { 521 bool b; 522 }; 523 524 /* Initialize and assign using boolean constants. */ 525 bool b = __lint_false; 526 b = __lint_true; 527 528 /* Access a struct member using the '.' operator. */ 529 struct bool_struct bs = { __lint_true }; 530 b = bs.b; 531 bs.b = b; 532 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 533 bs.b = 0; 534 535 /* Access a struct member using the '->' operator. */ 536 struct bool_struct *bsp = &bs; 537 b = bsp->b; 538 bsp->b = b; 539 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 540 bsp->b = 0; 541 } 542 543 int 544 strict_bool_operand_binary(bool b, int i) 545 { 546 547 /* The right-hand sides of these assignments are ok. */ 548 b = !b; 549 b = b && b; 550 b = b || b; 551 552 /* 553 * The right-hand sides of these assignments implicitly convert from 554 * scalar to bool. 555 */ 556 /* expect+1: error: operand of '!' must be bool, not 'int' [330] */ 557 b = !i; 558 /* expect+2: error: left operand of '&&' must be bool, not 'int' [331] */ 559 /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */ 560 b = i && i; 561 /* expect+2: error: left operand of '||' must be bool, not 'int' [331] */ 562 /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */ 563 b = i || i; 564 565 /* expect+1: error: right operand of '&&' must be bool, not 'int' [332] */ 566 b = b && 0; 567 /* expect+1: error: left operand of '&&' must be bool, not 'int' [331] */ 568 b = 0 && b; 569 /* expect+1: error: right operand of '||' must be bool, not 'int' [332] */ 570 b = b || 0; 571 /* expect+1: error: left operand of '||' must be bool, not 'int' [331] */ 572 b = 0 || b; 573 574 return i; 575 } 576 577 void 578 strict_bool_operand_unary_all(bool b) 579 { 580 b = !b; 581 /* expect+1: error: operand of '~' must not be bool [335] */ 582 b = ~b; 583 /* expect+1: error: operand of '++x' must not be bool [335] */ 584 ++b; 585 /* expect+1: error: operand of '--x' must not be bool [335] */ 586 --b; 587 /* expect+1: error: operand of 'x++' must not be bool [335] */ 588 b++; 589 /* expect+1: error: operand of 'x--' must not be bool [335] */ 590 b--; 591 /* expect+1: error: operand of '+' must not be bool [335] */ 592 b = +b; 593 /* expect+1: error: operand of '-' must not be bool [335] */ 594 b = -b; 595 } 596 597 void 598 strict_bool_operand_binary_all(bool b, unsigned u) 599 { 600 /* expect+2: error: left operand of '*' must not be bool [336] */ 601 /* expect+1: error: right operand of '*' must not be bool [337] */ 602 b = b * b; 603 /* expect+2: error: left operand of '/' must not be bool [336] */ 604 /* expect+1: error: right operand of '/' must not be bool [337] */ 605 b = b / b; 606 /* expect+2: error: left operand of '%' must not be bool [336] */ 607 /* expect+1: error: right operand of '%' must not be bool [337] */ 608 b = b % b; 609 /* expect+2: error: left operand of '+' must not be bool [336] */ 610 /* expect+1: error: right operand of '+' must not be bool [337] */ 611 b = b + b; 612 /* expect+2: error: left operand of '-' must not be bool [336] */ 613 /* expect+1: error: right operand of '-' must not be bool [337] */ 614 b = b - b; 615 /* expect+2: error: left operand of '<<' must not be bool [336] */ 616 /* expect+1: error: right operand of '<<' must not be bool [337] */ 617 b = b << b; 618 /* expect+2: error: left operand of '>>' must not be bool [336] */ 619 /* expect+1: error: right operand of '>>' must not be bool [337] */ 620 b = b >> b; 621 622 /* expect+2: error: left operand of '<' must not be bool [336] */ 623 /* expect+1: error: right operand of '<' must not be bool [337] */ 624 b = b < b; 625 /* expect+2: error: left operand of '<=' must not be bool [336] */ 626 /* expect+1: error: right operand of '<=' must not be bool [337] */ 627 b = b <= b; 628 /* expect+2: error: left operand of '>' must not be bool [336] */ 629 /* expect+1: error: right operand of '>' must not be bool [337] */ 630 b = b > b; 631 /* expect+2: error: left operand of '>=' must not be bool [336] */ 632 /* expect+1: error: right operand of '>=' must not be bool [337] */ 633 b = b >= b; 634 b = b == b; 635 b = b != b; 636 637 b = b & b; 638 b = b ^ b; 639 b = b | b; 640 b = b && b; 641 b = b || b; 642 b = b ? b : b; 643 644 b = b; 645 /* expect+2: error: left operand of '*=' must not be bool [336] */ 646 /* expect+1: error: right operand of '*=' must not be bool [337] */ 647 b *= b; 648 /* expect+2: error: left operand of '/=' must not be bool [336] */ 649 /* expect+1: error: right operand of '/=' must not be bool [337] */ 650 b /= b; 651 /* expect+2: error: left operand of '%=' must not be bool [336] */ 652 /* expect+1: error: right operand of '%=' must not be bool [337] */ 653 b %= b; 654 /* expect+2: error: left operand of '+=' must not be bool [336] */ 655 /* expect+1: error: right operand of '+=' must not be bool [337] */ 656 b += b; 657 /* expect+2: error: left operand of '-=' must not be bool [336] */ 658 /* expect+1: error: right operand of '-=' must not be bool [337] */ 659 b -= b; 660 /* expect+2: error: left operand of '<<=' must not be bool [336] */ 661 /* expect+1: error: right operand of '<<=' must not be bool [337] */ 662 b <<= b; 663 /* expect+2: error: left operand of '>>=' must not be bool [336] */ 664 /* expect+1: error: right operand of '>>=' must not be bool [337] */ 665 b >>= b; 666 b &= b; 667 b ^= b; 668 b |= b; 669 670 /* Operations with mixed types. */ 671 /* expect+1: error: left operand of '*' must not be bool [336] */ 672 u = b * u; 673 /* expect+1: error: right operand of '*' must not be bool [337] */ 674 u = u * b; 675 /* expect+1: error: left operand of '/' must not be bool [336] */ 676 u = b / u; 677 /* expect+1: error: right operand of '/' must not be bool [337] */ 678 u = u / b; 679 /* expect+1: error: left operand of '%' must not be bool [336] */ 680 u = b % u; 681 /* expect+1: error: right operand of '%' must not be bool [337] */ 682 u = u % b; 683 /* expect+1: error: left operand of '+' must not be bool [336] */ 684 u = b + u; 685 /* expect+1: error: right operand of '+' must not be bool [337] */ 686 u = u + b; 687 /* expect+1: error: left operand of '-' must not be bool [336] */ 688 u = b - u; 689 /* expect+1: error: right operand of '-' must not be bool [337] */ 690 u = u - b; 691 /* expect+1: error: left operand of '<<' must not be bool [336] */ 692 u = b << u; 693 /* expect+1: error: right operand of '<<' must not be bool [337] */ 694 u = u << b; 695 /* expect+1: error: left operand of '>>' must not be bool [336] */ 696 u = b >> u; 697 /* expect+1: error: right operand of '>>' must not be bool [337] */ 698 u = u >> b; 699 u = b ? u : u; 700 /* expect+1: error: operands of ':' have incompatible types '_Bool' and 'unsigned int' [107] */ 701 u = b ? b : u; 702 /* expect+1: error: operands of ':' have incompatible types 'unsigned int' and '_Bool' [107] */ 703 u = b ? u : b; 704 } 705 706 bool 707 strict_bool_operand_binary_comma(bool b, int i) 708 { 709 /* expect+1: warning: expression has null effect [129] */ 710 b = (b, !b); 711 /* expect+1: warning: expression has null effect [129] */ 712 i = (i, i + 1); 713 return b; 714 } 715 716 /* 717 * strict-bool-operator-result 718 */ 719 720 void 721 strict_bool_operator_result(bool b) 722 { 723 /* expect+1: error: operands of 'init' have incompatible types 'char' and '_Bool' [107] */ 724 char c = b; 725 /* expect+1: error: operands of 'init' have incompatible types 'int' and '_Bool' [107] */ 726 int i = b; 727 /* expect+1: error: operands of 'init' have incompatible types 'double' and '_Bool' [107] */ 728 double d = b; 729 /* expect+1: error: operands of 'init' have incompatible types 'pointer' and '_Bool' [107] */ 730 void *p = b; 731 732 /* The right-hand sides of these assignments are all ok. */ 733 b = !b; 734 b = i == i; 735 b = i != i; 736 b = i < i; 737 b = i <= i; 738 b = i >= i; 739 b = i > i; 740 b = b && b; 741 b = b || b; 742 743 /* 744 * The right-hand sides of these assignments are not ok, they 745 * implicitly convert from bool to int. 746 */ 747 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 748 i = !b; 749 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 750 i = i == i; 751 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 752 i = i != i; 753 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 754 i = i < i; 755 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 756 i = i <= i; 757 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 758 i = i >= i; 759 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 760 i = i > i; 761 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 762 i = b && b; 763 /* expect+1: error: operands of '=' have incompatible types 'int' and '_Bool' [107] */ 764 i = b || b; 765 } 766 767 768 /* 769 * strict-bool-bitwise-and 770 */ 771 772 enum Flags { 773 FLAG0 = 1 << 0, 774 FLAG1 = 1 << 1, 775 FLAG28 = 1 << 28 776 }; 777 778 /* expect+2: warning: parameter 'flags' unused in function 'strict_bool_bitwise_and_enum' [231] */ 779 void 780 strict_bool_bitwise_and_enum(enum Flags flags) 781 { 782 bool b; 783 784 /* 785 * FLAG0 has the value 1 and thus can be stored in a bool variable 786 * without truncation. Nevertheless this special case is not allowed 787 * because it would be too confusing if FLAG0 would work and all the 788 * other flags wouldn't. 789 */ 790 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 791 b = flags & FLAG0; 792 793 /* 794 * Assuming that FLAG1 is set in flags, a _Bool variable stores this 795 * as 1, as defined by C99 6.3.1.2. A uint8_t variable would store 796 * it as 2, as that is the integer value of FLAG1. Since FLAG1 fits 797 * in a uint8_t, no truncation takes place. 798 */ 799 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 800 b = flags & FLAG1; 801 802 /* 803 * In a _Bool variable, FLAG28 is stored as 1, since it is unequal to 804 * zero. In a uint8_t, the stored value would be 0 since bit 28 is 805 * out of range for a uint8_t and thus gets truncated. 806 */ 807 /* expect+1: error: operands of '=' have incompatible types '_Bool' and 'int' [107] */ 808 b = flags & FLAG28; 809 } 810 811 /* 812 * Demonstrate idiomatic code to query flags from an enum bit set. 813 * 814 * In all the controlling expressions in this function, the result of the 815 * operator '&' is compared against 0. This makes this pattern work, no 816 * matter whether the bits are in the low-value range or in the high-value 817 * range (such as FLAG28, which has the value 1073741824, which is more than 818 * what would fit into an unsigned char). Even if an enum could be extended 819 * to larger types than int, this pattern would work. 820 */ 821 bool 822 query_flag_from_enum_bit_set(enum Flags flags) 823 { 824 if (flags & FLAG0) 825 println("FLAG0 is set"); 826 827 if ((flags & FLAG1) != 0) 828 println("FLAG1 is set"); 829 830 if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1)) 831 println("FLAG0 and FLAG1 are both set"); 832 833 if (flags & FLAG0 && flags & FLAG1) 834 println("FLAG0 and FLAG1 are both set"); 835 836 if ((flags & (FLAG0 | FLAG1)) != 0) 837 println("At least one of FLAG0 and FLAG1 is set"); 838 839 if (flags & FLAG28) 840 println("FLAG28 is set"); 841 842 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 843 bool b0 = flags & FLAG0; 844 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 845 bool b1 = flags & FLAG1; 846 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 847 bool b28 = flags & FLAG28; 848 return b0 || b1 || b28; 849 } 850 851 bool 852 query_flag_from_int(int flags) 853 { 854 855 if (flags & FLAG0) 856 println("FLAG0 is set"); 857 858 if ((flags & FLAG1) != 0) 859 println("FLAG1 is set"); 860 861 if ((flags & (FLAG0 | FLAG1)) == (FLAG0 | FLAG1)) 862 println("FLAG0 and FLAG1 are both set"); 863 864 if (flags & FLAG0 && flags & FLAG1) 865 println("FLAG0 and FLAG1 are both set"); 866 867 if ((flags & (FLAG0 | FLAG1)) != 0) 868 println("At least one of FLAG0 and FLAG1 is set"); 869 870 if (flags & FLAG28) 871 println("FLAG28 is set"); 872 873 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 874 bool b0 = flags & FLAG0; 875 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 876 bool b1 = flags & FLAG1; 877 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 878 bool b28 = flags & FLAG28; 879 return b0 || b1 || b28; 880 } 881 882 883 void 884 strict_bool_operator_eq_bool_int(void) 885 { 886 /* expect+1: error: operands of '==' have incompatible types '_Bool' and 'int' [107] */ 887 (void)(strict_bool_conversion_return_false() == 0); 888 } 889 890 void 891 strict_bool_assign_bit_field_then_compare(void) 892 { 893 struct s { 894 bool flag: 1; 895 }; 896 897 struct s s = { __lint_false }; 898 899 /* expect+1: warning: expression has null effect [129] */ 900 (void)((s.flag = s.flag) != __lint_false); 901 } 902 903 void 904 bool_as_array_index(bool cond) 905 { 906 static const char *repr[] = { "no", "yes" }; 907 /* 908 * The '+' in the error message reveals that lint internally 909 * translates 'arr[ind]' to '*(arr + ind)' in an early stage of 910 * parsing. 911 */ 912 /* expect+1: error: right operand of '+' must not be bool [337] */ 913 println(repr[cond]); 914 println(cond ? "yes" : "no"); 915 } 916 917 void 918 initialization(void) 919 { 920 struct { 921 _Bool b; 922 } var[] = { 923 { __lint_false }, 924 { __lint_true }, 925 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 926 { 0 }, 927 /* expect+1: error: operands of 'init' have incompatible types '_Bool' and 'int' [107] */ 928 { 1 }, 929 }; 930 } 931