aboutsummaryrefslogtreecommitdiff
path: root/decl.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2024-04-14 23:34:15 -0700
committerMichael Forney <mforney@mforney.org>2024-04-15 01:24:32 -0700
commitfc501ceff7fefc6ea2fdd956e2c769fcd11d9fdd (patch)
tree1f2f5ba7c3b266ecb6f3fda93006f7cc2e09faf5 /decl.c
parentcc49fbc44550d3927c592445a3e7f89a4481a63a (diff)
decl: Save and re-open parameter scope for body
Diffstat (limited to 'decl.c')
-rw-r--r--decl.c49
1 files changed, 34 insertions, 15 deletions
diff --git a/decl.c b/decl.c
index 57c4a4d..96428ba 100644
--- a/decl.c
+++ b/decl.c
@@ -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;
}