aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-02-16 03:39:03 -0800
committerMichael Forney <mforney@mforney.org>2019-02-16 03:56:58 -0800
commit18ad54b003608f3060d4baf2fef00a8a2b6f0a7b (patch)
tree16b77a846ae70281c70a51fd253285e3abdb39a7
parent6dee4df79d5f251d12e387d8425e2b05cdd60523 (diff)
Allow labels with same name as typedef
-rw-r--r--pp.c3
-rw-r--r--stmt.c31
-rw-r--r--tests/label-typedef.c4
-rw-r--r--tests/label-typedef.qbe7
4 files changed, 33 insertions, 12 deletions
diff --git a/pp.c b/pp.c
index 41b67ed..af36686 100644
--- a/pp.c
+++ b/pp.c
@@ -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;
diff --git a/stmt.c b/stmt.c
index 8eced24..a5192c5 100644
--- a/stmt.c
+++ b/stmt.c
@@ -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
+}