scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 98caf6b9f86aa7e0af46d9de891e467364be6d2d
parent d6954f1a841ffe95aacc8c0e8a9dca44a087b1a6
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 18 Aug 2015 19:09:12 +0200

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.

Diffstat:
cc1/cc1.h | 3++-
cc1/cpp.c | 4++--
cc1/lex.c | 2+-
cc1/stmt.c | 38++++++++++++++++++++++----------------
cc1/symbol.c | 55++++++++++++++++++++++++++++++-------------------------
cc1/tests/test011.c | 2++
cc1/tests/test012.c | 3++-
7 files changed, 61 insertions(+), 46 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -311,13 +311,14 @@ extern Type *duptype(Type *base); /* 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); 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); diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -29,7 +29,7 @@ defmacro(char *s) Symbol *sym; strcpy(yytext, s); - sym = lookup(NS_CPP); + sym = lookup(NS_CPP, yytext); sym->flags |= ISDECLARED; return sym; } @@ -338,7 +338,7 @@ define(void) warn("'%s' redefined", yytext); free(sym->u.s); } else { - sym = lookup(NS_CPP); + sym = lookup(NS_CPP, yytext); sym->flags |= ISDECLARED; } diff --git a/cc1/lex.c b/cc1/lex.c @@ -378,7 +378,7 @@ iden(void) /* 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(); diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -22,6 +22,7 @@ label(void) 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 @@ While(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ For(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ Dowhile(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ Continue(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ Switch(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) 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 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) static void Default(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) { - Symbol *ldefault = newsym(NS_LABEL); + Symbol *ldefault = newlabel(); expect(DEFAULT); expect(':'); @@ -250,14 +256,14 @@ If(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) Symbol *end, *lelse; Node *np; - lelse = newsym(NS_LABEL); + lelse = newlabel(); expect(IF); np = condition(); emit(OBRANCH, lelse); 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); diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -110,9 +110,9 @@ popctx(void) 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 @@ newsym(unsigned ns) 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 @@ newsym(unsigned ns) return sym; if (ns == NS_LABEL) { sym->next = labels; - sym->id = newid(); return labels = sym; } @@ -201,18 +200,27 @@ newsym(unsigned ns) } 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 @@ lookup(unsigned ns) 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 @@ nextsym(Symbol *sym, unsigned ns) 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 @@ ikeywords(void) 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; } diff --git 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 { diff --git 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 @@ L21 } */ - +#line 1 int main()