diff options
-rw-r--r-- | pp.c | 3 | ||||
-rw-r--r-- | stmt.c | 31 | ||||
-rw-r--r-- | tests/label-typedef.c | 4 | ||||
-rw-r--r-- | tests/label-typedef.qbe | 7 |
4 files changed, 33 insertions, 12 deletions
@@ -112,7 +112,8 @@ next(void) bool peek(int kind) { - nextinto(&pending); + if (!pending.kind) + nextinto(&pending); if (pending.kind != kind) return false; pending.kind = TNONE; @@ -14,6 +14,23 @@ #include "token.h" #include "type.h" +static bool +gotolabel(struct function *f) +{ + char *name; + struct gotolabel *g; + + if (tok.kind != TIDENT) + return false; + name = tok.lit; + if (!peek(TCOLON)) + return false; + g = funcgoto(f, name); + g->defined = true; + funclabel(f, g->label); + return true; +} + /* 6.8 Statements and blocks */ void stmt(struct function *f, struct scope *s) @@ -25,6 +42,8 @@ stmt(struct function *f, struct scope *s) struct switchcases swtch = {0}; uint64_t i; + while (gotolabel(f)) + ; switch (tok.kind) { /* 6.8.1 Labeled statements */ case TCASE: @@ -55,7 +74,7 @@ stmt(struct function *f, struct scope *s) next(); s = mkscope(s); while (tok.kind != TRBRACE) { - if (!decl(s, f)) + if (gotolabel(f) || !decl(s, f)) stmt(f, s); } s = delscope(s); @@ -66,16 +85,6 @@ stmt(struct function *f, struct scope *s) case TSEMICOLON: next(); break; - case TIDENT: - name = tok.lit; - if (peek(TCOLON)) { - struct gotolabel *g = funcgoto(f, name); - g->defined = true; - funclabel(f, g->label); - stmt(f, s); - break; - } - /* fallthrough */ default: e = expr(s); v = funcexpr(f, e); diff --git a/tests/label-typedef.c b/tests/label-typedef.c new file mode 100644 index 0000000..f3744e3 --- /dev/null +++ b/tests/label-typedef.c @@ -0,0 +1,4 @@ +typedef int x; +void f(void) { +x:; +} diff --git a/tests/label-typedef.qbe b/tests/label-typedef.qbe new file mode 100644 index 0000000..b11f621 --- /dev/null +++ b/tests/label-typedef.qbe @@ -0,0 +1,7 @@ +export +function $f() { +@start.1 +@body.2 +@x.3 + ret +} |