commit 1c759c3cd3d169a1c58fd40b3b95d5766747accf
parent 64d12d9252d124d68ac2455a83db8bbd20dfd914
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 24 Apr 2014 15:32:15 +0200
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.
Diffstat:
3 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/cc1.h b/cc1.h
@@ -100,6 +100,7 @@ struct symbol {
bool isstatic : 1;
bool isauto : 1;
bool isregister : 1;
+ bool isdefined : 1;
} s;
union {
int i;
diff --git a/stmt.c b/stmt.c
@@ -12,14 +12,25 @@ extern Node * iszero(Node *np);
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 @@ condition(void)
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 @@ While(Symbol *lswitch)
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 @@ For(Symbol *lswitch)
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 @@ Break(Symbol *lbreak)
static void
Label(void)
{
- emitlabel(label(yytext));
+ emitlabel(label(yytext, 1));
expect(IDEN);
expect(':');
@@ -160,7 +179,7 @@ Goto(void)
if (yytoken != IDEN)
error("unexpected '%s'", yytext);
- emitjump(label(yytext), NULL);
+ emitjump(label(yytext, 0), NULL);
next();
expect(';');
}
diff --git a/symbol.c b/symbol.c
@@ -37,6 +37,8 @@ freesyms(uint8_t ns)
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);