Fix bug in ||, &&, ! (save registers through jumps), grischka-2005-09-25 case_2 This saves registers through jumps with ||, &&, and !. This patch was originally posted in grischka's 2005-09-25 email as "required fix" case_2 to compile gcc 2.95. It was tweaked by David A. Wheeler to merge the test case into the standard tcc test suite. The original test case only tested || (case 2.1) and ! (case 2.2); Wheeler added the test cases for && (which happens to completely crash the unpatched compiler at compiler time - pretty solid evidence of a problem in the unpatched program!). diff -ur tinycc-rl-1.0.0/tcc.c tinycc-grischka2/tcc.c --- tinycc-rl-1.0.0/tcc.c 2007-04-18 14:52:22.000000000 -0400 +++ tinycc-grischka2/tcc.c 2007-05-03 00:56:03.000000000 -0400 @@ -6482,8 +6482,10 @@ vtop->c.i = !vtop->c.i; else if ((vtop->r & VT_VALMASK) == VT_CMP) vtop->c.i = vtop->c.i ^ 1; - else + else { + save_regs(1); vseti(VT_JMP, gtst(1, 0)); + } break; case '~': next(); @@ -6896,6 +6898,7 @@ expr_or(); if (tok == TOK_LAND) { t = 0; + save_regs(1); for(;;) { t = gtst(1, t); if (tok != TOK_LAND) { @@ -6915,6 +6918,7 @@ expr_land(); if (tok == TOK_LOR) { t = 0; + save_regs(1); for(;;) { t = gtst(0, t); if (tok != TOK_LOR) { diff -ur tinycc-rl-1.0.0/tests/tcctest.c tinycc-grischka2/tests/tcctest.c --- tinycc-rl-1.0.0/tests/tcctest.c 2007-04-18 14:52:22.000000000 -0400 +++ tinycc-grischka2/tests/tcctest.c 2007-05-03 00:59:31.000000000 -0400 @@ -644,6 +644,29 @@ isid('g'), isid('T'), isid('(')); + + { + /* Check that tcc saves registers before a conditional jump */ + /* Addresses bug "grischka case_2" */ + struct test_str { int a, b, c; }; + struct test_str t1 = {0,0,0}; + struct test_str t2 = {1,1,1}; + struct test_str *p1 = &t1; + struct test_str *p2 = &t2; + int f = 0; + int g = 0; + + p1->b = f==0 || isid(0); + printf("case_2.1: Expect 0 1 0 -> %d %d %d\n", p1->a, p1->b, p1->c); + p1->c = !f || isid(0); + printf("case_2.2: Expect 0 1 1 -> %d %d %d\n", p1->a, p1->b, p1->c); + + /* This will crash old versions of tcc during compilation: */ + p2->b = (f==1) && isid(0); + printf("case_2.1AND: Expect 0 1 0 -> %d %d %d\n", p2->a, p2->b, p2->c); + p2->b = (!(f==1)) && isid(0); + printf("case_2.2AND: Expect 0 1 0 -> %d %d %d\n", p2->a, p2->b, p2->c); + } } int isid(int c)