If a condition is always zero/non-zero we can omit the then or else code. This is complicated a bit by having to deal with labels that might make such code reachable without us yet knowing during parsing.
Showing the changes to tests/tests2/87_dead_code.c (1 of 4 files). Show all
Unified · Split
| @@ -0,0 +1,122 @@ | ||
| 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 havok 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 | +} | |