1 | /* This checks various ways of dead code inside if statements
|
---|
2 | where there are non-obvious ways of how the code is actually
|
---|
3 | not dead due to reachable by labels. */
|
---|
4 | extern int printf (const char *, ...);
|
---|
5 | static void kb_wait_1(void)
|
---|
6 | {
|
---|
7 | unsigned long timeout = 2;
|
---|
8 | do {
|
---|
9 | /* Here the else arm is a statement expression that's supposed
|
---|
10 | to be suppressed. The label inside the while would unsuppress
|
---|
11 | code generation again if not handled correctly. And that
|
---|
12 | would wreak havoc to the cond-expression because there's no
|
---|
13 | jump-around emitted, the whole statement expression really
|
---|
14 | needs to not generate code (perhaps except useless forward jumps). */
|
---|
15 | (1 ?
|
---|
16 | printf("timeout=%ld\n", timeout) :
|
---|
17 | ({
|
---|
18 | int i = 1;
|
---|
19 | while (1)
|
---|
20 | while (i--)
|
---|
21 | some_label:
|
---|
22 | printf("error\n");
|
---|
23 | goto some_label;
|
---|
24 | })
|
---|
25 | );
|
---|
26 | timeout--;
|
---|
27 | } while (timeout);
|
---|
28 | }
|
---|
29 | int main (void)
|
---|
30 | {
|
---|
31 | int i = 1;
|
---|
32 | kb_wait_1();
|
---|
33 |
|
---|
34 | /* Simple test of dead code at first sight which isn't actually dead. */
|
---|
35 | if (0) {
|
---|
36 | yeah:
|
---|
37 | printf ("yeah\n");
|
---|
38 | } else {
|
---|
39 | printf ("boo\n");
|
---|
40 | }
|
---|
41 | if (i--)
|
---|
42 | goto yeah;
|
---|
43 |
|
---|
44 | /* Some more non-obvious uses where the problems are loops, so that even
|
---|
45 | the first loop statements aren't actually dead. */
|
---|
46 | i = 1;
|
---|
47 | if (0) {
|
---|
48 | while (i--) {
|
---|
49 | printf ("once\n");
|
---|
50 | enterloop:
|
---|
51 | printf ("twice\n");
|
---|
52 | }
|
---|
53 | }
|
---|
54 | if (i >= 0)
|
---|
55 | goto enterloop;
|
---|
56 |
|
---|
57 | /* The same with statement expressions. One might be tempted to
|
---|
58 | handle them specially by counting if inside statement exprs and
|
---|
59 | not unsuppressing code at loops at all then.
|
---|
60 | See kb_wait_1 for the other side of the medal where that wouldn't work. */
|
---|
61 | i = ({
|
---|
62 | int j = 1;
|
---|
63 | if (0) {
|
---|
64 | while (j--) {
|
---|
65 | printf ("SEonce\n");
|
---|
66 | enterexprloop:
|
---|
67 | printf ("SEtwice\n");
|
---|
68 | }
|
---|
69 | }
|
---|
70 | if (j >= 0)
|
---|
71 | goto enterexprloop;
|
---|
72 | j; });
|
---|
73 |
|
---|
74 | /* The other two loop forms: */
|
---|
75 | i = 1;
|
---|
76 | if (0) {
|
---|
77 | for (i = 1; i--;) {
|
---|
78 | printf ("once2\n");
|
---|
79 | enterloop2:
|
---|
80 | printf ("twice2\n");
|
---|
81 | }
|
---|
82 | }
|
---|
83 | if (i > 0)
|
---|
84 | goto enterloop2;
|
---|
85 |
|
---|
86 | i = 1;
|
---|
87 | if (0) {
|
---|
88 | do {
|
---|
89 | printf ("once3\n");
|
---|
90 | enterloop3:
|
---|
91 | printf ("twice3\n");
|
---|
92 | } while (i--);
|
---|
93 | }
|
---|
94 | if (i > 0)
|
---|
95 | goto enterloop3;
|
---|
96 |
|
---|
97 | /* And check that case and default labels have the same effect
|
---|
98 | of disabling code suppression. */
|
---|
99 | i = 41;
|
---|
100 | switch (i) {
|
---|
101 | if (0) {
|
---|
102 | printf ("error\n");
|
---|
103 | case 42:
|
---|
104 | printf ("error2\n");
|
---|
105 | case 41:
|
---|
106 | printf ("caseok\n");
|
---|
107 | }
|
---|
108 | }
|
---|
109 |
|
---|
110 | i = 41;
|
---|
111 | switch (i) {
|
---|
112 | if (0) {
|
---|
113 | printf ("error3\n");
|
---|
114 | default:
|
---|
115 | printf ("caseok2\n");
|
---|
116 | break;
|
---|
117 | case 42:
|
---|
118 | printf ("error4\n");
|
---|
119 | }
|
---|
120 | }
|
---|
121 | return 0;
|
---|
122 | }
|
---|