msg_193.c revision 1.22 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