diff options
author | Michael Forney <mforney@mforney.org> | 2024-04-14 23:34:15 -0700 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2024-04-15 01:24:32 -0700 |
commit | fc501ceff7fefc6ea2fdd956e2c769fcd11d9fdd (patch) | |
tree | 1f2f5ba7c3b266ecb6f3fda93006f7cc2e09faf5 /decl.c | |
parent | cc49fbc44550d3927c592445a3e7f89a4481a63a (diff) |
decl: Save and re-open parameter scope for body
Diffstat (limited to 'decl.c')
-rw-r--r-- | decl.c | 49 |
1 files changed, 34 insertions, 15 deletions
@@ -537,11 +537,11 @@ is used for the qualifiers of the base type). This is corrected in declarator(). */ static void -declaratortypes(struct scope *s, struct list *result, char **name, bool allowabstract) +declaratortypes(struct scope *s, struct list *result, char **name, struct scope **funcscope, bool allowabstract) { - struct list *ptr; + struct list *ptr, *prev; struct type *t; - struct decl **p; + struct decl *d, **paramend; struct expr *e; enum typequal tq; bool allowattr; @@ -557,6 +557,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs if (name) *name = NULL; ptr = result->next; + prev = ptr->prev; switch (tok.kind) { case TLPAREN: next(); @@ -574,7 +575,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs goto func; } } - declaratortypes(s, result, name, allowabstract); + declaratortypes(s, result, name, funcscope, allowabstract); expect(TRPAREN, "after parenthesized declarator"); allowattr = false; break; @@ -601,10 +602,14 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs t->u.func.isnoreturn = false; t->u.func.params = NULL; t->u.func.nparam = 0; - p = &t->u.func.params; + paramend = &t->u.func.params; + s = mkscope(s); while (tok.kind != TRPAREN) { - *p = parameter(s); - p = &(*p)->next; + d = parameter(s); + if (d->name) + scopeputdecl(s, d); + *paramend = d; + paramend = &d->next; ++t->u.func.nparam; if (!consume(TCOMMA)) break; @@ -613,7 +618,14 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs break; } } - if (t->u.func.nparam == 1 && !t->u.func.isvararg && t->u.func.params->type->kind == TYPEVOID && !t->u.func.params->name) { + if (funcscope && ptr->prev == prev) { + /* we may need to re-open the scope later if this is a function definition */ + *funcscope = s; + s = s->parent; + } else { + s = delscope(s); + } + if (t->u.func.nparam == 1 && !t->u.func.isvararg && d->type->kind == TYPEVOID && !d->name) { t->u.func.params = NULL; t->u.func.nparam = 0; } @@ -655,14 +667,16 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs } static struct qualtype -declarator(struct scope *s, struct qualtype base, char **name, bool allowabstract) +declarator(struct scope *s, struct qualtype base, char **name, struct scope **funcscope, bool allowabstract) { struct type *t; enum typequal tq; struct expr *e; struct list result = {&result, &result}, *l, *prev; - declaratortypes(s, &result, name, allowabstract); + if (funcscope) + *funcscope = NULL; + declaratortypes(s, &result, name, funcscope, allowabstract); for (l = result.prev; l != &result; l = prev) { prev = l->prev; t = listelement(l, struct type, link); @@ -715,7 +729,7 @@ parameter(struct scope *s) error(&tok.loc, "no type in parameter declaration"); if (sc && sc != SCREGISTER) error(&tok.loc, "parameter declaration has invalid storage-class specifier"); - t = declarator(s, t, &name, true); + t = declarator(s, t, &name, NULL, true); t.type = typeadjust(t.type, &t.qual); return mkdecl(name, DECLOBJECT, t.type, t.qual, LINKNONE); } @@ -855,7 +869,7 @@ structdecl(struct scope *s, struct structbuilder *b) width = intconstexpr(s, false); addmember(b, base, NULL, 0, width); } else { - mt = declarator(s, base, &name, false); + mt = declarator(s, base, &name, NULL, false); width = consume(TCOLON) ? intconstexpr(s, false) : -1; addmember(b, mt, name, align, width); } @@ -874,7 +888,7 @@ typename(struct scope *s, enum typequal *tq) t = declspecs(s, NULL, NULL, NULL); if (t.type) { - t = declarator(s, t, NULL, true); + t = declarator(s, t, NULL, NULL, true); if (tq) *tq |= t.qual; } @@ -957,6 +971,7 @@ decl(struct scope *s, struct func *f) int allowfunc = !f; struct decl *d, *prior; enum declkind kind; + struct scope *funcscope; int align; if (staticassert(s)) @@ -983,7 +998,7 @@ decl(struct scope *s, struct func *f) return true; } for (;;) { - qt = declarator(s, base, &name, false); + qt = declarator(s, base, &name, &funcscope, false); t = qt.type; tq = qt.qual; if (consume(T__ASM__)) { @@ -1051,7 +1066,9 @@ decl(struct scope *s, struct func *f) error(&tok.loc, "function definition not allowed"); if (d->defined) error(&tok.loc, "function '%s' redefined", name); - s = mkscope(&filescope); + /* re-open scope from function declarator */ + assert(funcscope); + s = funcscope; f = mkfunc(d, name, t, s); stmt(f, s); /* XXX: need to keep track of function in case a later declaration specifies extern */ @@ -1061,6 +1078,8 @@ decl(struct scope *s, struct func *f) delfunc(f); d->defined = true; return true; + } else if (funcscope) { + delscope(funcscope); } break; } |