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