aboutsummaryrefslogtreecommitdiff
path: root/decl.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-02-17 00:57:33 -0800
committerMichael Forney <mforney@mforney.org>2019-02-17 00:57:33 -0800
commit863fec184fdb150f4f8758cc68eb6a51f9a38dfe (patch)
tree63f78075067fcded66226eff2968663feb83ec73 /decl.c
parent7d746860bda62c2f382bc0ac82d4d6c8cdf6c7b2 (diff)
Improve old-style function declaration support
Implement typecompatible for types created with non-prototype function declarations. Require a function definition with parameter declaration list after a declaration with a non-empty identifier list. Detect function definitions with parameter declaration lists containing types incompatible with the promoted types, and report an error for now.
Diffstat (limited to 'decl.c')
-rw-r--r--decl.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/decl.c b/decl.c
index 3e574b2..cb2e2f4 100644
--- a/decl.c
+++ b/decl.c
@@ -498,6 +498,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs
break;
}
expect(TRPAREN, "to close function declarator");
+ t->func.paraminfo = t->func.isprototype || t->func.params || tok.kind == TLBRACE;
listinsert(ptr->prev, &t->link);
break;
case TLBRACK: /* array declarator */
@@ -816,6 +817,19 @@ decl(struct scope *s, struct function *f)
t->func.isnoreturn |= fs & FUNCNORETURN;
if (f && sc && sc != SCEXTERN) /* 6.7.1p7 */
error(&tok.loc, "function '%s' with block scope may only have storage class 'extern'", name);
+ if (!t->func.isprototype && t->func.paraminfo) {
+ if (!allowfunc)
+ error(&tok.loc, "function declaration not allowed");
+ /* collect type information for parameters before we check compatibility */
+ while (paramdecl(s, t->func.params))
+ ;
+ if (tok.kind != TLBRACE)
+ error(&tok.loc, "function declaration with identifier list is not part of definition");
+ for (p = t->func.params; p; p = p->next) {
+ if (!p->type)
+ error(&tok.loc, "old-style function definition does not declare '%s'", p->name);
+ }
+ }
if (d) {
if (!typecompatible(t, d->type))
error(&tok.loc, "function '%s' redeclared with incompatible type", name);
@@ -838,19 +852,6 @@ decl(struct scope *s, struct function *f)
break;
}
switch (tok.kind) {
- default:
- if (!allowfunc || kind != DECLFUNC || t->func.isprototype)
- error(&tok.loc, "expected ',' or ';' after declarator");
- /* K&R-style function definition */
- while (paramdecl(s, t->func.params))
- ;
- for (p = t->func.params; p; p = p->next) {
- if (!p->type)
- error(&tok.loc, "old-style function definition does not declare '%s'", p->name);
- }
- if (tok.kind != TLBRACE)
- error(&tok.loc, "expected compound statement after function declarator");
- /* fallthrough */
case TLBRACE:
if (!allowfunc)
error(&tok.loc, "function declaration not allowed");
@@ -870,6 +871,8 @@ decl(struct scope *s, struct function *f)
case TSEMICOLON:
next();
return true;
+ default:
+ error(&tok.loc, "expected ',' or ';' after declarator");
}
}
}