ref: 1c759c3cd3d169a1c58fd40b3b95d5766747accf
parent: 64d12d9252d124d68ac2455a83db8bbd20dfd914
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Apr 24 11:32:15 EDT 2014
Detect when a label used in a goto is not defined We cannot know that a goto label is not defined until the end of a function, so the best place for this check is in the free stage, where we can be sure that the label is not going to be defined.
--- a/cc1.h
+++ b/cc1.h
@@ -100,6 +100,7 @@
bool isstatic : 1;
bool isauto : 1;
bool isregister : 1;
+ bool isdefined : 1;
} s;
union {
int i;
--- a/stmt.c
+++ b/stmt.c
@@ -12,14 +12,25 @@
static void stmt(Symbol *lbreak, Symbol *lcont, Symbol *lswitch);
static Symbol *
-label(char *s)
+label(char *s, char define)
{
- if (!s)
+ Symbol *sym;
+
+ if (s) {
+ if ((sym = lookup(s, NS_LABEL)) != NULL) {
+ if (define && sym->s.isdefined)
+ error("label '%s' already defined", s);
+ else
+ sym->s.isdefined = 1;
+ return sym;
+ }
+ } else {
s = "";
- else if (lookup(s, NS_LABEL))
- error("label '%s' already defined", s);
+ }
- return install(s, NS_LABEL);
+ sym = install(s, NS_LABEL);
+ sym->s.isdefined = define;
+ return sym;
}
static void
@@ -45,9 +56,13 @@
static void
While(Symbol *lswitch)
{
- Symbol *begin= label(NULL), *cond = label(NULL), *end = label(NULL);
+ Symbol *begin, *cond, *end;
Node *np;
+ begin = label(NULL, 1);
+ end = label(NULL, 1);
+ cond = label(NULL, 1);
+
expect(WHILE);
np = condition();
emitjump(cond, NULL);
@@ -63,9 +78,13 @@
static void
For(Symbol *lswitch)
{
- Symbol *begin= label(NULL), *cond = label(NULL), *end = label(NULL);
+ Symbol *begin, *cond, *end;
Node *econd = NULL, *einc = NULL;
+ begin = label(NULL, 1);
+ end = label(NULL, 1);
+ cond = label(NULL, 1);
+
expect(FOR);
expect('(');
stmtexp();
@@ -92,7 +111,7 @@
static void
Dowhile(Symbol *lswitch)
{
- Symbol *begin= label(NULL), *end = label(NULL);
+ Symbol *begin= label(NULL, 1), *end = label(NULL, 1);
expect(DO);
@@ -137,7 +156,7 @@
static void
Label(void)
{
- emitlabel(label(yytext));
+ emitlabel(label(yytext, 1));
expect(IDEN);
expect(':');
@@ -160,7 +179,7 @@
if (yytoken != IDEN)
error("unexpected '%s'", yytext);
- emitjump(label(yytext), NULL);
+ emitjump(label(yytext, 0), NULL);
next();
expect(';');
}
--- a/symbol.c
+++ b/symbol.c
@@ -37,6 +37,8 @@
for (sym = tbl->head; sym; sym = next) {
if (sym->ctx <= curctx)
break;
+ if (ns == NS_LABEL && !sym->s.isdefined)
+ error("label '%s' is not defined", sym->name);
tbl->htab[hash(sym->name)] = sym->hash;
next = tbl->head = sym->next;
free(sym->name);