fix VLA/continue issue

as reported in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00131.html. Note
that this is one of two separate VLA bugs:

 A. labels aren't reached by program execution, so the stack pointer is
 never saved
 B. continue doesn't restore the stack pointer as goto does

This fixes only B. I'm not sure whether the same issue applies to break
as well as continue.

Add a test case, but disable tests #78 and #79 for now as they're not
fully fixed until the issue described in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00110.html
is resolved.
This commit is contained in:
Philip 2015-04-27 16:38:27 +00:00
parent bd489a4815
commit d2dd6fdbfb
4 changed files with 122 additions and 2 deletions

View File

@ -4794,6 +4794,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
} else if (tok == TOK_WHILE) { } else if (tok == TOK_WHILE) {
next(); next();
d = ind; d = ind;
if (vla_flags & VLA_IN_SCOPE) {
gen_vla_sp_restore(*vla_sp_loc);
vla_flags |= VLA_NEED_NEW_FRAME;
}
skip('('); skip('(');
gexpr(); gexpr();
skip(')'); skip(')');
@ -4958,6 +4962,13 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
/* compute jump */ /* compute jump */
if (!csym) if (!csym)
tcc_error("cannot continue"); 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); *csym = gjmp(*csym);
next(); next();
skip(';'); skip(';');
@ -4980,6 +4991,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
skip(';'); skip(';');
d = ind; d = ind;
c = ind; c = ind;
if (vla_flags & VLA_IN_SCOPE) {
gen_vla_sp_restore(*vla_sp_loc);
vla_flags |= VLA_NEED_NEW_FRAME;
}
a = 0; a = 0;
b = 0; b = 0;
if (tok != ';') { if (tok != ';') {
@ -4990,6 +5005,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
if (tok != ')') { if (tok != ')') {
e = gjmp(0); e = gjmp(0);
c = ind; c = ind;
if (vla_flags & VLA_IN_SCOPE) {
gen_vla_sp_restore(*vla_sp_loc);
vla_flags |= VLA_NEED_NEW_FRAME;
}
gexpr(); gexpr();
vpop(); vpop();
gjmp_addr(d); gjmp_addr(d);
@ -5008,6 +5027,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
a = 0; a = 0;
b = 0; b = 0;
d = ind; 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); block(&a, &b, case_sym, def_sym, case_reg, 0);
skip(TOK_WHILE); skip(TOK_WHILE);
skip('('); skip('(');

View File

@ -0,0 +1,92 @@
#include <stdio.h>
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;
}

View File

@ -0,0 +1,4 @@
OK
OK
OK
OK

View File

@ -96,8 +96,9 @@ TESTS = \
74_nocode_wanted.test \ 74_nocode_wanted.test \
75_array_in_struct_init.test \ 75_array_in_struct_init.test \
76_dollars_in_identifiers.test \ 76_dollars_in_identifiers.test \
77_push_pop_macro.test \ 77_push_pop_macro.test
78_vla_label.test # 78_vla_label.test -- currently broken
# 79_vla_continue.test -- currently broken
# 34_array_assignment.test -- array assignment is not in C standard # 34_array_assignment.test -- array assignment is not in C standard