aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccgen.c23
-rw-r--r--tests/tests2/79_vla_continue.c92
-rw-r--r--tests/tests2/79_vla_continue.expect4
-rw-r--r--tests/tests2/Makefile5
4 files changed, 122 insertions, 2 deletions
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 <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;
+}
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