Home | History | Annotate | Line # | Download | only in lint1
      1 /*	$NetBSD: msg_193.c,v 1.22 2024/11/13 04:32:49 rillig Exp $	*/
      2 # 3 "msg_193.c"
      3 
      4 // Test for message: '%s' 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 
     27 extern void reachable(void);
     28 extern void unreachable(void);
     29 extern _Bool maybe(void);
     30 
     31 
     32 void
     33 test_statement(void)
     34 {
     35 	reachable();
     36 	reachable();
     37 }
     38 
     39 void
     40 test_compound_statement(void)
     41 {
     42 	reachable();
     43 	{
     44 		reachable();
     45 		reachable();
     46 	}
     47 	reachable();
     48 }
     49 
     50 void
     51 test_if_statement(void)
     52 {
     53 	if (1)
     54 		reachable();
     55 	reachable();
     56 	if (0)
     57 		unreachable();		/* expect+0: ... [193] */
     58 	reachable();
     59 }
     60 
     61 void
     62 test_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 
     87 void
     88 test_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 
     99 void
    100 test_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 
    115 void
    116 test_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 
    140 void
    141 test_if_return(void)
    142 {
    143 	if (1)
    144 		return;
    145 	unreachable();			/* expect+0: ... [193] */
    146 }
    147 
    148 void
    149 test_if_else_return(void)
    150 {
    151 	if (1)
    152 		reachable();
    153 	else
    154 		return;			/* expect+0: ... [193] */
    155 	reachable();
    156 }
    157 
    158 void
    159 test_for_forever(void)
    160 {
    161 	for (;;)
    162 		reachable();
    163 	unreachable();			/* expect+0: ... [193] */
    164 }
    165 
    166 void
    167 test_for_true(void)
    168 {
    169 	for (; 1;)
    170 		reachable();
    171 	unreachable();			/* expect+0: ... [193] */
    172 }
    173 
    174 void
    175 test_for_false(void)
    176 {
    177 	for (; 0;)
    178 		unreachable();		/* expect+0: ... [193] */
    179 	reachable();
    180 }
    181 
    182 void
    183 test_for_break(void)
    184 {
    185 	for (;;) {
    186 		reachable();
    187 		break;
    188 		unreachable();		/* expect+0: ... [193] */
    189 	}
    190 	reachable();
    191 }
    192 
    193 void
    194 test_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 
    213 void
    214 test_for_continue(void)
    215 {
    216 	for (;;) {
    217 		reachable();
    218 		continue;
    219 		unreachable();		/* expect+0: ... [193] */
    220 	}
    221 	unreachable();			/* expect+0: ... [193] */
    222 }
    223 
    224 void
    225 test_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 
    244 void
    245 test_for_return(void)
    246 {
    247 	for (;;) {
    248 		reachable();
    249 		return;
    250 		unreachable();		/* expect+0: ... [193] */
    251 	}
    252 	unreachable();			/* expect+0: ... [193] */
    253 }
    254 
    255 void
    256 test_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 
    275 void
    276 test_while_true(void)
    277 {
    278 	while (1)
    279 		reachable();
    280 	unreachable();			/* expect+0: ... [193] */
    281 }
    282 
    283 void
    284 test_while_false(void)
    285 {
    286 	while (0)
    287 		unreachable();		/* expect+0: ... [193] */
    288 	reachable();
    289 }
    290 
    291 void
    292 test_while_break(void)
    293 {
    294 	while (1) {
    295 		reachable();
    296 		break;
    297 		unreachable();		/* expect+0: ... [193] */
    298 	}
    299 	reachable();
    300 }
    301 
    302 void
    303 test_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 
    322 void
    323 test_while_continue(void)
    324 {
    325 	while (1) {
    326 		reachable();
    327 		continue;
    328 		unreachable();		/* expect+0: ... [193] */
    329 	}
    330 	unreachable();			/* expect+0: ... [193] */
    331 }
    332 
    333 void
    334 test_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 
    353 void
    354 test_while_return(void)
    355 {
    356 	while (1) {
    357 		reachable();
    358 		return;
    359 		unreachable();		/* expect+0: ... [193] */
    360 	}
    361 	unreachable();			/* expect+0: ... [193] */
    362 }
    363 
    364 void
    365 test_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 
    384 void
    385 test_do_while_true(void)
    386 {
    387 	do {
    388 		reachable();
    389 	} while (1);
    390 	unreachable();			/* expect+0: ... [193] */
    391 }
    392 
    393 void
    394 test_do_while_false(void)
    395 {
    396 	do {
    397 		reachable();
    398 	} while (0);
    399 	reachable();
    400 }
    401 
    402 void
    403 test_do_while_break(void)
    404 {
    405 	do {
    406 		reachable();
    407 		break;
    408 		unreachable();		/* expect+0: ... [193] */
    409 	} while (1);
    410 	reachable();
    411 }
    412 
    413 void
    414 test_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 
    433 void
    434 test_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 
    444 void
    445 test_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 
    464 void
    465 test_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 
    475 void
    476 test_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 
    495 void
    496 test_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 
    529 void
    530 test_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  */
    566 void
    567 test_goto_numbers_alphabetically(void)
    568 {
    569 	goto one;
    570 eight:
    571 	goto nine;
    572 five:
    573 	return;
    574 four:
    575 	goto five;
    576 nine:
    577 	goto ten;
    578 one:
    579 	goto two;
    580 seven:
    581 	goto eight;
    582 six:
    583 	/* expect-1: warning: label 'six' unused in function 'test_goto_numbers_alphabetically' [232] */
    584 	goto seven;
    585 ten:
    586 	return;
    587 three:
    588 	goto four;
    589 two:
    590 	goto three;
    591 }
    592 
    593 void
    594 test_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] */
    601 out:
    602 	reachable();
    603 }
    604 
    605 void
    606 test_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. */
    613 unreachable:
    614 	unreachable();
    615 reachable:
    616 	reachable();
    617 }
    618 
    619 /* TODO: switch */
    620 
    621 /* TODO: system-dependent constant expression (see tn_system_dependent) */
    622 
    623 void suppressed(void);
    624 
    625 void
    626 lint_annotation_NOTREACHED(void)
    627 {
    628 	if (0) {
    629 		/* expect+1: warning: 'call' 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: 'if' 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  */
    667 int
    668 test_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: 'empty' 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  */
    714 void
    715 invalid_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