1/* $NetBSD: msg_193.c,v 1.21 2023/03/28 14:44:35 rillig Exp $ */ 2# 3 "msg_193.c" 3 4// Test for message: statement not reached [193] 5 6/* lint1-extra-flags: -X 351 */ 7 8/* 9 * Test the reachability of statements in a function. 10 * 11 * if 12 * if-else 13 * if-else-if-else 14 * for 15 * while 16 * do-while 17 * switch 18 * break 19 * continue 20 * goto 21 * return 22 * 23 * constant expression 24 * system-dependent constant expression 25 */ 26 27extern void reachable(void); 28extern void unreachable(void); 29extern _Bool maybe(void); 30 31 32void 33test_statement(void) 34{ 35 reachable(); 36 reachable(); 37} 38 39void 40test_compound_statement(void) 41{ 42 reachable(); 43 { 44 reachable(); 45 reachable(); 46 } 47 reachable(); 48} 49 50void 51test_if_statement(void) 52{ 53 if (1) 54 reachable(); 55 reachable(); 56 if (0) 57 unreachable(); /* expect+0: ... [193] */ 58 reachable(); 59} 60 61void 62test_if_compound_statement(void) 63{ 64 if (1) { 65 reachable(); 66 } 67 if (1) { 68 { 69 { 70 reachable(); 71 } 72 } 73 } 74 75 if (0) { 76 unreachable(); /* expect+0: ... [193] */ 77 } 78 if (0) { 79 { 80 { 81 unreachable(); /* expect+0: ... [193] */ 82 } 83 } 84 } 85} 86 87void 88test_if_without_else(void) 89{ 90 if (1) 91 reachable(); 92 reachable(); 93 94 if (0) 95 unreachable(); /* expect+0: ... [193] */ 96 reachable(); 97} 98 99void 100test_if_with_else(void) 101{ 102 if (1) 103 reachable(); 104 else 105 unreachable(); /* expect+0: ... [193] */ 106 reachable(); 107 108 if (0) 109 unreachable(); /* expect+0: ... [193] */ 110 else 111 reachable(); 112 reachable(); 113} 114 115void 116test_if_else_if_else(void) 117{ 118 if (1) 119 reachable(); 120 else if (1) /* expect+0: ... [193] */ 121 unreachable(); 122 else 123 unreachable(); /* expect+0: ... [193] */ 124 125 if (0) 126 unreachable(); /* expect+0: ... [193] */ 127 else if (1) 128 reachable(); 129 else 130 unreachable(); /* expect+0: ... [193] */ 131 132 if (0) 133 unreachable(); /* expect+0: ... [193] */ 134 else if (0) 135 unreachable(); /* expect+0: ... [193] */ 136 else 137 reachable(); 138} 139 140void 141test_if_return(void) 142{ 143 if (1) 144 return; 145 unreachable(); /* expect+0: ... [193] */ 146} 147 148void 149test_if_else_return(void) 150{ 151 if (1) 152 reachable(); 153 else 154 return; /* expect+0: ... [193] */ 155 reachable(); 156} 157 158void 159test_for_forever(void) 160{ 161 for (;;) 162 reachable(); 163 unreachable(); /* expect+0: ... [193] */ 164} 165 166void 167test_for_true(void) 168{ 169 for (; 1;) 170 reachable(); 171 unreachable(); /* expect+0: ... [193] */ 172} 173 174void 175test_for_false(void) 176{ 177 for (; 0;) 178 unreachable(); /* expect+0: ... [193] */ 179 reachable(); 180} 181 182void 183test_for_break(void) 184{ 185 for (;;) { 186 reachable(); 187 break; 188 unreachable(); /* expect+0: ... [193] */ 189 } 190 reachable(); 191} 192 193void 194test_for_if_break(void) 195{ 196 for (;;) { 197 reachable(); 198 if (0) { 199 unreachable(); /* expect+0: ... [193] */ 200 break; 201 unreachable(); /* expect+0: ... [193] */ 202 } 203 if (1) { 204 reachable(); 205 break; 206 unreachable(); /* expect+0: ... [193] */ 207 } 208 unreachable(); /* expect+0: ... [193] */ 209 } 210 reachable(); 211} 212 213void 214test_for_continue(void) 215{ 216 for (;;) { 217 reachable(); 218 continue; 219 unreachable(); /* expect+0: ... [193] */ 220 } 221 unreachable(); /* expect+0: ... [193] */ 222} 223 224void 225test_for_if_continue(void) 226{ 227 for (;;) { 228 reachable(); 229 if (0) { 230 unreachable(); /* expect+0: ... [193] */ 231 continue; 232 unreachable(); /* expect+0: ... [193] */ 233 } 234 if (1) { 235 reachable(); 236 continue; 237 unreachable(); /* expect+0: ... [193] */ 238 } 239 unreachable(); /* expect+0: ... [193] */ 240 } 241 unreachable(); /* expect+0: ... [193] */ 242} 243 244void 245test_for_return(void) 246{ 247 for (;;) { 248 reachable(); 249 return; 250 unreachable(); /* expect+0: ... [193] */ 251 } 252 unreachable(); /* expect+0: ... [193] */ 253} 254 255void 256test_for_if_return(void) 257{ 258 for (;;) { 259 reachable(); 260 if (0) { 261 unreachable(); /* expect+0: ... [193] */ 262 return; 263 unreachable(); /* expect+0: ... [193] */ 264 } 265 if (1) { 266 reachable(); 267 return; 268 unreachable(); /* expect+0: ... [193] */ 269 } 270 unreachable(); /* expect+0: ... [193] */ 271 } 272 unreachable(); /* expect+0: ... [193] */ 273} 274 275void 276test_while_true(void) 277{ 278 while (1) 279 reachable(); 280 unreachable(); /* expect+0: ... [193] */ 281} 282 283void 284test_while_false(void) 285{ 286 while (0) 287 unreachable(); /* expect+0: ... [193] */ 288 reachable(); 289} 290 291void 292test_while_break(void) 293{ 294 while (1) { 295 reachable(); 296 break; 297 unreachable(); /* expect+0: ... [193] */ 298 } 299 reachable(); 300} 301 302void 303test_while_if_break(void) 304{ 305 while (1) { 306 reachable(); 307 if (0) { 308 unreachable(); /* expect+0: ... [193] */ 309 break; 310 unreachable(); /* expect+0: ... [193] */ 311 } 312 if (1) { 313 reachable(); 314 break; 315 unreachable(); /* expect+0: ... [193] */ 316 } 317 unreachable(); /* expect+0: ... [193] */ 318 } 319 reachable(); 320} 321 322void 323test_while_continue(void) 324{ 325 while (1) { 326 reachable(); 327 continue; 328 unreachable(); /* expect+0: ... [193] */ 329 } 330 unreachable(); /* expect+0: ... [193] */ 331} 332 333void 334test_while_if_continue(void) 335{ 336 while (1) { 337 reachable(); 338 if (0) { 339 unreachable(); /* expect+0: ... [193] */ 340 continue; 341 unreachable(); /* expect+0: ... [193] */ 342 } 343 if (1) { 344 reachable(); 345 continue; 346 unreachable(); /* expect+0: ... [193] */ 347 } 348 unreachable(); /* expect+0: ... [193] */ 349 } 350 unreachable(); /* expect+0: ... [193] */ 351} 352 353void 354test_while_return(void) 355{ 356 while (1) { 357 reachable(); 358 return; 359 unreachable(); /* expect+0: ... [193] */ 360 } 361 unreachable(); /* expect+0: ... [193] */ 362} 363 364void 365test_while_if_return(void) 366{ 367 while (1) { 368 reachable(); 369 if (0) { 370 unreachable(); /* expect+0: ... [193] */ 371 return; 372 unreachable(); /* expect+0: ... [193] */ 373 } 374 if (1) { 375 reachable(); 376 return; 377 unreachable(); /* expect+0: ... [193] */ 378 } 379 unreachable(); /* expect+0: ... [193] */ 380 } 381 unreachable(); /* expect+0: ... [193] */ 382} 383 384void 385test_do_while_true(void) 386{ 387 do { 388 reachable(); 389 } while (1); 390 unreachable(); /* expect+0: ... [193] */ 391} 392 393void 394test_do_while_false(void) 395{ 396 do { 397 reachable(); 398 } while (0); 399 reachable(); 400} 401 402void 403test_do_while_break(void) 404{ 405 do { 406 reachable(); 407 break; 408 unreachable(); /* expect+0: ... [193] */ 409 } while (1); 410 reachable(); 411} 412 413void 414test_do_while_if_break(void) 415{ 416 do { 417 reachable(); 418 if (0) { 419 unreachable(); /* expect+0: ... [193] */ 420 break; 421 unreachable(); /* expect+0: ... [193] */ 422 } 423 if (1) { 424 reachable(); 425 break; 426 unreachable(); /* expect+0: ... [193] */ 427 } 428 unreachable(); /* expect+0: ... [193] */ 429 } while (1); 430 reachable(); 431} 432 433void 434test_do_while_continue(void) 435{ 436 do { 437 reachable(); 438 continue; 439 unreachable(); /* expect+0: ... [193] */ 440 } while (1); 441 unreachable(); /* expect+0: ... [193] */ 442} 443 444void 445test_do_while_if_continue(void) 446{ 447 do { 448 reachable(); 449 if (0) { 450 unreachable(); /* expect+0: ... [193] */ 451 continue; 452 unreachable(); /* expect+0: ... [193] */ 453 } 454 if (1) { 455 reachable(); 456 continue; 457 unreachable(); /* expect+0: ... [193] */ 458 } 459 unreachable(); /* expect+0: ... [193] */ 460 } while (1); 461 unreachable(); /* expect+0: ... [193] */ 462} 463 464void 465test_do_while_return(void) 466{ 467 do { 468 reachable(); 469 return; 470 unreachable(); /* expect+0: ... [193] */ 471 } while (1); 472 unreachable(); /* expect+0: ... [193] */ 473} 474 475void 476test_do_while_if_return(void) 477{ 478 do { 479 reachable(); 480 if (0) { 481 unreachable(); /* expect+0: ... [193] */ 482 return; 483 unreachable(); /* expect+0: ... [193] */ 484 } 485 if (1) { 486 reachable(); 487 return; 488 unreachable(); /* expect+0: ... [193] */ 489 } 490 unreachable(); /* expect+0: ... [193] */ 491 } while (1); 492 unreachable(); /* expect+0: ... [193] */ 493} 494 495void 496test_if_nested(void) 497{ 498 if (0) { 499 if (1) /* expect+0: ... [193] */ 500 unreachable(); 501 else 502 unreachable(); /* expect+0: ... [193] *//* XXX: redundant */ 503 504 if (0) 505 unreachable(); /* expect+0: ... [193] *//* XXX: redundant */ 506 else 507 unreachable(); 508 509 unreachable(); 510 } 511 reachable(); 512 513 if (1) { 514 if (1) 515 reachable(); 516 else 517 unreachable(); /* expect+0: ... [193] */ 518 519 if (0) 520 unreachable(); /* expect+0: ... [193] */ 521 else 522 reachable(); 523 524 reachable(); 525 } 526 reachable(); 527} 528 529void 530test_if_maybe(void) 531{ 532 if (maybe()) { 533 if (0) 534 unreachable(); /* expect+0: ... [193] */ 535 else 536 reachable(); 537 reachable(); 538 } 539 reachable(); 540 541 if (0) { 542 if (maybe()) /* expect+0: ... [193] */ 543 unreachable(); 544 else 545 unreachable(); 546 unreachable(); 547 } 548 reachable(); 549 550 if (1) { 551 if (maybe()) 552 reachable(); 553 else 554 reachable(); 555 reachable(); 556 } 557 reachable(); 558} 559 560/* 561 * To compute the reachability graph of this little monster, lint would have 562 * to keep all statements and their relations from the whole function in 563 * memory. It doesn't do that. Therefore it does not warn about any 564 * unreachable statements in this function. 565 */ 566void 567test_goto_numbers_alphabetically(void) 568{ 569 goto one; 570eight: 571 goto nine; 572five: 573 return; 574four: 575 goto five; 576nine: 577 goto ten; 578one: 579 goto two; 580seven: 581 goto eight; 582six: 583 /* expect-1: warning: label 'six' unused in function 'test_goto_numbers_alphabetically' [232] */ 584 goto seven; 585ten: 586 return; 587three: 588 goto four; 589two: 590 goto three; 591} 592 593void 594test_while_goto(void) 595{ 596 while (1) { 597 goto out; 598 break; /* lint only warns with the -b option */ 599 } 600 unreachable(); /* expect+0: ... [193] */ 601out: 602 reachable(); 603} 604 605void 606test_unreachable_label(void) 607{ 608 if (0) 609 goto unreachable; /* expect+0: ... [193] */ 610 goto reachable; 611 612 /* named_label assumes that any label is reachable. */ 613unreachable: 614 unreachable(); 615reachable: 616 reachable(); 617} 618 619/* TODO: switch */ 620 621/* TODO: system-dependent constant expression (see tn_system_dependent) */ 622 623void suppressed(void); 624 625void 626lint_annotation_NOTREACHED(void) 627{ 628 if (0) { 629 /* expect+1: warning: statement not reached [193] */ 630 unreachable(); 631 } 632 633 if (0) { 634 /* NOTREACHED */ 635 suppressed(); 636 } 637 638 if (0) 639 /* NOTREACHED */ 640 suppressed(); 641 642 if (1) { 643 reachable(); 644 } 645 646 if (1) { 647 /* NOTREACHED */ 648 suppressed(); 649 } 650 651 /* 652 * Since the condition in the 'if' statement is constant, lint knows 653 * that the branch is unconditionally taken. The annotation comment 654 * marks that branch as not reached, which means that any following 655 * statement cannot be reached as well. 656 */ 657 /* expect+1: warning: statement not reached [193] */ 658 if (1) 659 /* NOTREACHED */ 660 suppressed(); 661} 662 663/* 664 * Since at least 2002 and before cgram.y 1.379 from 2022-01-16, lint did not 665 * detect a double semicolon. See cgram.y, expression_statement, T_SEMI. 666 */ 667int 668test_null_statement(void) 669{ 670 /* 671 * The following 2 semicolons are superfluous but lint doesn't warn 672 * about them. Probably it should. A null statement as part of a 673 * block-list has no use. 674 */ 675 ;; 676 677 /* 678 * If assertions are disabled with -DNDEBUG and __lint__ is defined, 679 * NetBSD's <assert.h> defines assert(x) to nothing, leaving only 680 * the trailing semicolon. If there are several assertions next to 681 * each other, without any whitespace in between (very unusual), the 682 * GCC preprocessor generates ";;" for them, which makes them 683 * indistinguishable from the literal ";;" from the typo above. 684 * 685 * (echo '#include <assert.h>'; echo 'assert(0);assert(1);') \ 686 * | gcc -DNDEBUG -E - -D__lint__ 687 * 688 * To actually see the difference, lint would need to look at the 689 * code before preprocessing and compare it with the preprocessed 690 * code, which would be a lot of work. 691 * 692 * Apart from the above edge case, detecting extra semicolons would 693 * be possible, but lint would have to look at the whitespace between 694 * the tokens, and this is something that it doesn't do at all, as of 695 * 2022-01-16. 696 */ 697 698 /* 699 * A stand-alone null statement, on the other hand, has its purpose. 700 * Without it, the 'for' loop would not be complete. The NetBSD 701 * style is to use 'continue;' instead of a simple ';'. 702 */ 703 for (int i = 0; i < 10; i++) 704 ; 705 706 /* expect+1: warning: statement not reached [193] */ 707 return 0;; 708} 709 710/* 711 * Before func.c 1.149 from 2023-02-21, lint crashed due to a null pointer 712 * dereference. 713 */ 714void 715invalid_case_expression(void) 716{ 717 switch (4) { 718 /* expect+1: error: operand of '~' has invalid type 'double' [108] */ 719 case ~0.0: 720 ; 721 } 722} 723