diff --git a/tccgen.c b/tccgen.c index b490c04..2cc57bd 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5692,13 +5692,15 @@ static void block(int *bsym, int *csym, int is_expr) a = gjmp(a); /* add implicit break */ /* case lookup */ gsym(b); - qsort(sw.p, sw.n, sizeof(void*), case_cmp); - for (b = 1; b < sw.n; b++) - if (sw.p[b - 1]->v2 >= sw.p[b]->v1) - tcc_error("duplicate case value"); - gcase(sw.p, sw.n, c, &a); - if (sw.def_sym) - gjmp_addr(sw.def_sym); + if (!nocode_wanted) { + qsort(sw.p, sw.n, sizeof(void*), case_cmp); + for (b = 1; b < sw.n; b++) + if (sw.p[b - 1]->v2 >= sw.p[b]->v1) + tcc_error("duplicate case value"); + gcase(sw.p, sw.n, c, &a); + if (sw.def_sym) + gjmp_addr(sw.def_sym); + } dynarray_reset(&sw.p, &sw.n); cur_switch = saved; /* break label */ diff --git a/tests/tcctest.c b/tests/tcctest.c index bdbcb60..7b1ac1a 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -2964,6 +2964,56 @@ void test_high_clobbers(void) #endif } +static long cpu_number; +void trace_console(long len, long len2) +{ + /* This generated invalid code when the emission of the switch + table isn't disabled. The asms are necessary to show the bug, + normal statements don't work (they need to generate some code + even under nocode_wanted, which normal statements don't do, + but asms do). Also at least these number of cases is necessary + to generate enough "random" bytes. They ultimately are enough + to create invalid instruction patterns to which the first + skip-to-decision-table jump jumps. If decision table emission + is disabled all of this is no problem. + + It also is necessary that the switches are in a statement expression + (which has the property of not being enterable from outside. no + matter what). */ + if (0 + && + ({ + long pscr_ret__; + switch(len) { + case 4: + { + long pfo_ret__; + switch (len2) { + case 8: printf("bla"); pfo_ret__ = 42; break; + } + pscr_ret__ = pfo_ret__; + } + break; + case 8: + { + long pfo_ret__; + switch (len2) { + case 1:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 2:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 4:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + case 8:asm("movq %1,%0": "=r" (pfo_ret__) : "m" (cpu_number)); break; + default: printf("impossible\n"); + } + pscr_ret__ = pfo_ret__; + }; + break; + } + pscr_ret__; + })) + { + printf("huh?\n"); + } +} void asm_test(void) { char buf[128]; @@ -3044,6 +3094,7 @@ void asm_test(void) asm volatile ("mov $0x4243, %%esi" : "=r" (regvar)); printf ("regvar=%x\n", regvar); test_high_clobbers(); + trace_console(8, 8); return; label1: goto label2;