shithub: scc

Download patch

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);