xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_193.c (revision 6937eff333b197fb14840f0e58df0f7a0edfd51a)
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