Add support for the continue statement
Add error check for a break statement that's not inside a loop. (We just
generated bad code before. Oops!)
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index d9cecdd..9840197 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -5003,7 +5003,7 @@
return pGen->gtst(0, 0);
}
- void block(intptr_t l, bool outermostFunctionBlock) {
+ void block(int* breakLabel, int continueAddress, bool outermostFunctionBlock) {
intptr_t a, n, t;
Type* pBaseType;
@@ -5015,12 +5015,12 @@
skip('(');
a = test_expr();
skip(')');
- block(l, false);
+ block(breakLabel, continueAddress, false);
if (tok == TOK_ELSE) {
next();
n = pGen->gjmp(0); /* jmp */
pGen->gsym(a);
- block(l, false);
+ block(breakLabel, continueAddress, false);
pGen->gsym(n); /* patch else jmp */
} else {
pGen->gsym(a); /* patch if test */
@@ -5050,7 +5050,7 @@
}
}
skip(')');
- block((intptr_t) &a, false);
+ block(&a, n, false);
pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */
pGen->gsym(a);
} else if (tok == '{') {
@@ -5059,7 +5059,7 @@
}
next();
while (tok != '}' && tok != EOF)
- block(l, false);
+ block(breakLabel, continueAddress, false);
skip('}');
if (! outermostFunctionBlock) {
mLocals.popLevel();
@@ -5081,7 +5081,17 @@
}
rsym = pGen->gjmp(rsym); /* jmp */
} else if (accept(TOK_BREAK)) {
- *(int *) l = pGen->gjmp(*(int *) l);
+ if (breakLabel) {
+ *breakLabel = pGen->gjmp(*breakLabel);
+ } else {
+ error("break statement must be within a for, do, while, or switch statement");
+ }
+ } else if (accept(TOK_CONTINUE)) {
+ if (continueAddress) {
+ pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset());
+ } else {
+ error("continue statement must be within a for, do, or while statement");
+ }
} else if (tok != ';')
commaExpr();
skip(';');
@@ -5907,7 +5917,7 @@
rsym = loc = 0;
pReturnType = pDecl->pHead;
a = pGen->functionEntry(pDecl);
- block(0, true);
+ block(0, 0, true);
pGen->gsym(rsym);
pGen->functionExit(pDecl, a, loc);
mLocals.popLevel();
diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c
new file mode 100644
index 0000000..d8b8e36
--- /dev/null
+++ b/libacc/tests/data/continue.c
@@ -0,0 +1,13 @@
+int main() {
+ int i, j, sum;
+ sum = 0;
+ for (i = 0; i < 10; i++) {
+ if (i & 1) continue;
+ for (j = 0; j < 10; j++) {
+ if (j & 1) continue;
+ sum += i * j;
+ }
+ }
+ return sum;
+}
+
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index 6e0899c..d93af46 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -187,6 +187,10 @@
self.compileCheck(["-R", "data/returnval-ansi.c"],
"Executing compiled code:\nresult: 42\n")
+ def testContinue(self):
+ self.compileCheck(["-R", "data/continue.c"],
+ "Executing compiled code:\nresult: 400\n")
+
def testStringLiteralConcatenation(self):
self.compileCheck(["-R", "data/testStringConcat.c"],
"Executing compiled code:\nresult: 13\n", "Hello, world\n")