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