shithub: scc

Download patch

ref: 98caf6b9f86aa7e0af46d9de891e467364be6d2d
parent: d6954f1a841ffe95aacc8c0e8a9dca44a087b1a6
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Aug 18 15:09:12 EDT 2015

Fix errors in reuse of non defined symbols

There were several errors when a symbol reused some previous
non declared symbol in a different namespace, because it was
not covering the possibility that the symbol already existed.

--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -311,7 +311,7 @@
 
 /* symbol.c */
 extern void dumpstab(char *msg);
-extern Symbol *lookup(unsigned ns);
+extern Symbol *lookup(unsigned ns, char *name);
 extern Symbol *nextsym(Symbol *sym, unsigned ns);
 extern Symbol *install(unsigned ns, Symbol *sym);
 extern Symbol *newsym(unsigned ns);
@@ -318,6 +318,7 @@
 extern void pushctx(void), popctx(void);
 extern void ikeywords(void);
 extern void delmacro(Symbol *sym);
+extern Symbol *newlabel(void);
 
 /* stmt.c */
 extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -29,7 +29,7 @@
 	Symbol *sym;
 
 	strcpy(yytext, s);
-	sym = lookup(NS_CPP);
+	sym = lookup(NS_CPP, yytext);
 	sym->flags |= ISDECLARED;
 	return sym;
 }
@@ -338,7 +338,7 @@
 		warn("'%s' redefined", yytext);
 		free(sym->u.s);
 	} else {
-		sym = lookup(NS_CPP);
+		sym = lookup(NS_CPP, yytext);
 		sym->flags |= ISDECLARED;
 	}
 
--- a/cc1/lex.c
+++ b/cc1/lex.c
@@ -378,7 +378,7 @@
 		/* nothing */;
 	input->p = p;
 	tok2str();
-	sym = lookup(lex_ns);
+	sym = lookup(lex_ns, yytext);
 	if (sym->ns == NS_CPP) {
 		if (!disexpand && expand(begin, sym))
 			return next();
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
@@ -22,6 +22,7 @@
 	case TYPEIDEN:
 		if ((sym = install(NS_LABEL, yylval.sym)) == NULL)
 			error("label '%s' already defined", yytoken);
+		sym->flags |= ISDEFINED;
 		emit(OLABEL, sym);
 		next();
 		expect(':');
@@ -51,9 +52,9 @@
 	Symbol *begin, *cond, *end;
 	Node *np;
 
-	begin = newsym(NS_LABEL);
-	end = newsym(NS_LABEL);
-	cond = newsym(NS_LABEL);
+	begin = newlabel();
+	end = newlabel();
+	cond = newlabel();
 
 	expect(WHILE);
 	np = condition();
@@ -74,9 +75,9 @@
 	Symbol *begin, *cond, *end;
 	Node *econd, *einc, *einit;
 
-	begin = newsym(NS_LABEL);
-	end = newsym(NS_LABEL);
-	cond = newsym(NS_LABEL);
+	begin = newlabel();
+	end = newlabel();
+	cond = newlabel();
 
 	expect(FOR);
 	expect('(');
@@ -106,8 +107,8 @@
 	Symbol *begin, *end;
 	Node *np;
 
-	begin = newsym(NS_LABEL);
-	end = newsym(NS_LABEL);
+	begin = newlabel();
+	end = newlabel();
 	expect(DO);
 	emit(OBLOOP, NULL);
 	emit(OLABEL, begin);
@@ -166,12 +167,17 @@
 static void
 Goto(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
 {
+	Symbol *sym;
+
 	setnamespace(NS_LABEL);
 	next();
 	if (yytoken != IDEN)
 		unexpected();
-	yylval.sym->flags |= ISUSED;
-	emit(OJUMP, yylval.sym);
+	sym = yylval.sym;
+	if ((sym->flags & ISDECLARED) == 0)
+		sym = install(NS_LABEL, sym);
+	sym->flags |= ISUSED;
+	emit(OJUMP, sym);
 	next();
 	expect(';');
 }
@@ -198,8 +204,8 @@
 	expect (')');
 
 	lcase.expr = cond;
-	lcase.lbreak = newsym(NS_LABEL);
-	lcase.ltable = newsym(NS_LABEL);
+	lcase.lbreak = newlabel();
+	lcase.ltable = newlabel();
 
 	emit(OSWITCH, &lcase);
 	stmt(lbreak, lcont, &lcase);
@@ -224,7 +230,7 @@
 	pcase = xmalloc(sizeof(*pcase));
 	pcase->expr = np;
 	pcase->next = lswitch->head;
-	emit(OLABEL, pcase->label = newsym(NS_LABEL));
+	emit(OLABEL, pcase->label = newlabel());
 	lswitch->head = pcase;
 	if (++lswitch->nr == NR_SWITCH)
 		error("too case labels for a switch statement");
@@ -234,7 +240,7 @@
 static void
 Default(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
 {
-	Symbol *ldefault = newsym(NS_LABEL);
+	Symbol *ldefault = newlabel();
 
 	expect(DEFAULT);
 	expect(':');
@@ -250,7 +256,7 @@
 	Symbol *end, *lelse;
 	Node *np;
 
-	lelse = newsym(NS_LABEL);
+	lelse = newlabel();
 	expect(IF);
 	np = condition();
 	emit(OBRANCH, lelse);
@@ -257,7 +263,7 @@
 	emit(OEXPR, negate(np));
 	stmt(lbreak, lcont, lswitch);
 	if (accept(ELSE)) {
-		end = newsym(NS_LABEL);
+		end = newlabel();
 		emit(OJUMP, end);
 		emit(OLABEL, lelse);
 		stmt(lbreak, lcont, lswitch);
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -110,9 +110,9 @@
 		for (sym = labels; sym; sym = next) {
 			next = sym->next;
 			f = sym->flags;
-			if ((f & (ISUSED|ISDECLARED)) == ISDECLARED)
+			if ((f & (ISUSED|ISDEFINED)) == ISDEFINED)
 				warn("'%s' defined but not used", sym->name);
-			if ((f & ISDECLARED) == 0)
+			if ((f & ISDEFINED) == 0)
 				printerr("label '%s' is not defined", sym->name);
 			free(sym->name);
 			free(sym);
@@ -171,7 +171,7 @@
 	sym->ns = ns;
 	sym->ctx = (ns == NS_CPP) ? UCHAR_MAX : curctx;
 	sym->token = IDEN;
-	sym->flags = ISDECLARED;
+	sym->flags = ISDECLARED | ISUSED;
 	sym->u.s = sym->name = NULL;
 	sym->type = NULL;
 	sym->next = sym->hash = NULL;
@@ -180,7 +180,6 @@
 		return sym;
 	if (ns == NS_LABEL) {
 		sym->next = labels;
-		sym->id = newid();
 		return labels = sym;
 	}
 
@@ -201,18 +200,27 @@
 }
 
 Symbol *
-lookup(unsigned ns)
+newlabel(void)
 {
+	Symbol *sym = newsym(NS_LABEL);
+	sym->id = newid();
+	sym->flags |= ISDEFINED;
+	return sym;
+}
+
+Symbol *
+lookup(unsigned ns, char *name)
+{
 	Symbol *sym, **h;
 	unsigned sns, v;
 	char *t, c;
 
-	v = hash(yytext);
+	v = hash(name);
 	h = &htab[v];
-	c = *yytext;
+	c = *name;
 	for (sym = *h; sym; sym = sym->hash) {
 		t = sym->name;
-		if (*t != c || strcmp(t, yytext))
+		if (*t != c || strcmp(t, name))
 			continue;
 		sns = sym->ns;
 		if (sns == NS_KEYWORD || sns == NS_CPP)
@@ -221,8 +229,8 @@
 			continue;
 		return sym;
 	}
-	sym = linkhash(newsym(ns), yytext, v);
-	sym->flags &= ~ISDECLARED;
+	sym = linkhash(newsym(ns), name, v);
+	sym->flags &= ~(ISDECLARED | ISUSED);
 
 	return sym;
 }
@@ -263,21 +271,19 @@
 Symbol *
 install(unsigned ns, Symbol *sym)
 {
-	if (sym->ctx == curctx) {
-		if (sym->flags & ISDECLARED) {
-			if (ns == sym->ns)
-				return NULL;
-		} else {
-			sym->flags |= ISDECLARED;
-			sym->ns = ns;
-			goto assign_id;
-		}
+	if (sym->ctx == curctx && ns == sym->ns) {
+		if (sym->flags & ISDECLARED)
+			return NULL;
+	} else {
+		sym = lookup(ns, sym->name);
+		if (sym->flags & ISDECLARED)
+			return sym;
 	}
-	sym = linkhash(newsym(ns), sym->name, hash(sym->name));
 
-assign_id:
-	if (sym->ns != NS_CPP || sym->ns != NS_LABEL)
-		sym->id = newid();
+	sym->flags |= ISDECLARED;
+	if (ns == NS_CPP)
+		return sym;
+	sym->id = newid();
 
 	return sym;
 }
@@ -348,8 +354,7 @@
 
 	for (lp = list; *lp; ++lp) {
 		for (bp = *lp; bp->str; ++bp) {
-			strcpy(yytext, bp->str);
-			sym = lookup(ns);
+			sym = lookup(ns, bp->str);
 			sym->token = bp->token;
 			sym->u.token = bp->value;
 		}
--- a/cc1/tests/test011.c
+++ b/cc1/tests/test011.c
@@ -2,6 +2,8 @@
 name: TEST011
 description: Basic test for goto
 output:
+test011.c:14: warning: 'foo' defined but not used
+test011.c:14: warning: 'start' defined but not used
 F1
 G1	F1	main
 {
--- a/cc1/tests/test012.c
+++ b/cc1/tests/test012.c
@@ -2,6 +2,7 @@
 name: TEST012
 description: Basic switch test
 output:
+test012.c:39: warning: 'foo' defined but not used
 F1
 G1	F1	main
 {
@@ -70,7 +71,7 @@
 }
 */
 
-
+#line 1
 
 int
 main()