From fa2bdd711212ba6b7a94a20971e8bfa281e73296 Mon Sep 17 00:00:00 2001 From: Uneven Prankster Date: Wed, 12 Jul 2023 13:22:29 -0300 Subject: lol --- tinycc/tests/tests2/87_dead_code.c | 165 +++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 tinycc/tests/tests2/87_dead_code.c (limited to 'tinycc/tests/tests2/87_dead_code.c') diff --git a/tinycc/tests/tests2/87_dead_code.c b/tinycc/tests/tests2/87_dead_code.c new file mode 100644 index 0000000..369f4ba --- /dev/null +++ b/tinycc/tests/tests2/87_dead_code.c @@ -0,0 +1,165 @@ +/* This checks various ways of dead code inside if statements + where there are non-obvious ways of how the code is actually + not dead due to reachable by labels. */ +extern int printf (const char *, ...); +static void kb_wait_1(void) +{ + unsigned long timeout = 2; + do { + /* Here the else arm is a statement expression that's supposed + to be suppressed. The label inside the while would unsuppress + code generation again if not handled correctly. And that + would wreak havoc to the cond-expression because there's no + jump-around emitted, the whole statement expression really + needs to not generate code (perhaps except useless forward jumps). */ + (1 ? + printf("timeout=%ld\n", timeout) : + ({ + int i = 1; + while (1) + while (i--) + some_label: + printf("error\n"); + goto some_label; + }) + ); + timeout--; + } while (timeout); +} + +static int global; + +static void foo(int i) +{ + global+=i; + printf ("g=%d\n", global); +} + +static int check(void) +{ + printf ("check %d\n", global); + return 1; +} + +static void dowhile(void) +{ + do { + foo(1); + if (global == 1) { + continue; + } else if (global == 2) { + continue; + } + /* The following break shouldn't disable the check() call, + as it's reachable by the continues above. */ + break; + } while (check()); +} + +static void nondead_after_dead_return(void) +{ + /* This statement expr is not entered, and hence that fact that it + doesn't fall-through should not influence the surrounding code. */ + 0 && ({ return; 0;}); + printf ("nondead works\n"); + return; +} + +int main (void) +{ + int i = 1; + kb_wait_1(); + + /* Simple test of dead code at first sight which isn't actually dead. */ + if (0) { +yeah: + printf ("yeah\n"); + } else { + printf ("boo\n"); + } + if (i--) + goto yeah; + + /* Some more non-obvious uses where the problems are loops, so that even + the first loop statements aren't actually dead. */ + i = 1; + if (0) { + while (i--) { + printf ("once\n"); +enterloop: + printf ("twice\n"); + } + } + if (i >= 0) + goto enterloop; + + /* The same with statement expressions. One might be tempted to + handle them specially by counting if inside statement exprs and + not unsuppressing code at loops at all then. + See kb_wait_1 for the other side of the medal where that wouldn't work. */ + i = ({ + int j = 1; + if (0) { + while (j--) { + printf ("SEonce\n"); + enterexprloop: + printf ("SEtwice\n"); + } + } + if (j >= 0) + goto enterexprloop; + j; }); + + /* The other two loop forms: */ + i = 1; + if (0) { + for (i = 1; i--;) { + printf ("once2\n"); +enterloop2: + printf ("twice2\n"); + } + } + if (i > 0) + goto enterloop2; + + i = 1; + if (0) { + do { + printf ("once3\n"); +enterloop3: + printf ("twice3\n"); + } while (i--); + } + if (i > 0) + goto enterloop3; + + /* And check that case and default labels have the same effect + of disabling code suppression. */ + i = 41; + switch (i) { + if (0) { + printf ("error\n"); + case 42: + printf ("error2\n"); + case 41: + printf ("caseok\n"); + } + } + + i = 41; + switch (i) { + if (0) { + printf ("error3\n"); + default: + printf ("caseok2\n"); + break; + case 42: + printf ("error4\n"); + } + } + + dowhile(); + nondead_after_dead_return(); + + return 0; +} -- cgit v1.2.3