diff --git a/tccgen.c b/tccgen.c index 5275b47..88b8c72 100644 --- a/tccgen.c +++ b/tccgen.c @@ -4794,6 +4794,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, } else if (tok == TOK_WHILE) { next(); d = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } skip('('); gexpr(); skip(')'); @@ -4958,6 +4962,13 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, /* compute jump */ if (!csym) tcc_error("cannot continue"); + if (vla_flags & VLA_IN_SCOPE) { + /* If VLAs are in use, save the current stack pointer and + reset the stack pointer to what it was at function entry + (label will restore stack pointer in inner scopes) */ + vla_sp_save(); + gen_vla_sp_restore(vla_sp_root_loc); + } *csym = gjmp(*csym); next(); skip(';'); @@ -4980,6 +4991,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip(';'); d = ind; c = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } a = 0; b = 0; if (tok != ';') { @@ -4990,6 +5005,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if (tok != ')') { e = gjmp(0); c = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } gexpr(); vpop(); gjmp_addr(d); @@ -5008,6 +5027,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, a = 0; b = 0; d = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } block(&a, &b, case_sym, def_sym, case_reg, 0); skip(TOK_WHILE); skip('('); diff --git a/tests/tests2/79_vla_continue.c b/tests/tests2/79_vla_continue.c new file mode 100644 index 0000000..9c48c1d --- /dev/null +++ b/tests/tests2/79_vla_continue.c @@ -0,0 +1,92 @@ +#include + +int f(void) +{ + return 5; +} + +void test1() +{ + int count = 10; + void *addr[10]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test2() +{ + int count = 10; + void *addr[count]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test3() +{ + int count = 10; + void *addr[count]; + while(count--) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test4() +{ + int count = 10; + void *addr[count]; + do { + int a[f()]; + + addr[count] = a; + + continue; + } while(count--); + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +int main(void) +{ + test1(); + test2(); + test3(); + test4(); + + return 0; +} diff --git a/tests/tests2/79_vla_continue.expect b/tests/tests2/79_vla_continue.expect new file mode 100644 index 0000000..b462a5a --- /dev/null +++ b/tests/tests2/79_vla_continue.expect @@ -0,0 +1,4 @@ +OK +OK +OK +OK diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 470716b..6148c0b 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -96,8 +96,9 @@ TESTS = \ 74_nocode_wanted.test \ 75_array_in_struct_init.test \ 76_dollars_in_identifiers.test \ - 77_push_pop_macro.test \ - 78_vla_label.test + 77_push_pop_macro.test +# 78_vla_label.test -- currently broken +# 79_vla_continue.test -- currently broken # 34_array_assignment.test -- array assignment is not in C standard