ref: b9081437c83b589ac0618b12c555bdbc9897279f
parent: f7b3cb04badaa5b42b9f0af83af837ab32b0336b
author: Roberto E. Vargas Caballero <[email protected]>
date: Sat Sep 26 08:36:59 EDT 2015
Improve error recovery in argument parsing
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -116,18 +116,6 @@
push(dp, ARY, n);
}
-static void
-newpar(Type *fun, Type *par)
-{
- TINT n = fun->n.elem;
-
- if (n == NR_FUNPARAM)
- error("too much parameters in function definition");
- fun->p.pars = xrealloc(fun->p.pars, ++n * sizeof(Type *));
- fun->p.pars[n-1] = par;
- fun->n.elem = n;
-}
-
static Symbol *
parameter(struct decl *dcl)
{
@@ -138,9 +126,6 @@
sym->type = tp;
- if (n == -1)
- error("'void' must be the only parameter");
-
switch (dcl->sclass) {
case STATIC:
case EXTERN:
@@ -157,26 +142,30 @@
switch (tp->op) {
case VOID:
- if (n != 0)
- error("incorrect void parameter");
- if (dcl->sclass)
- error("void as unique parameter may not be qualified");
+ if (n != 0) {
+ errorp("incorrect void parameter");
+ return NULL;
+ }
funtp->n.elem = -1;
+ if (dcl->sclass)
+ errorp("void as unique parameter may not be qualified");
return NULL;
case ARY:
tp = mktype(tp->type, PTR, 0, NULL);
break;
case FTN:
- error("incorrect function type for a function parameter");
+ errorp("incorrect function type for a function parameter");
+ return NULL;
}
if (name) {
- if ((sym = install(NS_IDEN, sym)) == NULL)
- error("redefinition of parameter '%s'", name);
+ if ((sym = install(NS_IDEN, sym)) == NULL) {
+ errorp("redefinition of parameter '%s'", name);
+ return NULL;
+ }
}
sym->type = tp;
sym->flags |= ISUSED; /* avoid non used warnings in prototypes */
- newpar(funtp, tp);
return sym;
}
@@ -189,35 +178,62 @@
static void
fundcl(struct declarators *dp)
{
- Type type;
- Symbol *syms[NR_FUNPARAM], **sp = syms;
+ Type type, *types[NR_FUNPARAM], *tp;
+ Symbol *syms[NR_FUNPARAM], *sym;
TINT size;
- Symbol *pars = NULL;
+ Symbol *pars;
+ int toomany = 0, toovoid = 0;
pushctx();
expect('(');
type.n.elem = 0;
- type.p.pars = NULL;
- if (accept(')')) {
- newpar(&type, ellipsistype);
- *sp++ = NULL;
- } else {
- do {
- if (!accept(ELLIPSIS)) {
- *sp++ = dodcl(0, parameter, NS_IDEN, &type);
- } else {
- newpar(&type, ellipsistype);
- *sp++ = NULL;
- break;
- }
- } while (accept(','));
-
- expect(')');
+ if (yytoken == ')') {
+ ++type.n.elem;
+ syms[0] = NULL;
+ types[0] = ellipsistype;
+ goto end_params;
}
- if (type.n.elem != -1) {
+ do {
+ if (type.n.elem == -1) {
+ if (!toovoid)
+ errorp("'void' must be the only parameter");
+ toovoid = 1;
+ }
+ if (!accept(ELLIPSIS)) {
+ sym = dodcl(0, parameter, NS_IDEN, &type);
+ if (!sym)
+ continue;
+ tp = sym->type;
+ } else {
+ if (type.n.elem == 0)
+ errorp("a named argument is requiered before '...'");
+ tp = ellipsistype;
+ sym = NULL;
+ }
+ if (type.n.elem == NR_FUNPARAM) {
+ if (toomany)
+ continue;
+ errorp("too much parameters in function definition");
+ toomany = 1;
+ } else if (type.n.elem >= 0) {
+ syms[type.n.elem] = sym;
+ types[type.n.elem] = tp;
+ ++type.n.elem;
+ }
+ } while (tp != ellipsistype && accept(','));
+
+end_params:
+ expect(')');
+
+ if (type.n.elem > 0) {
size = type.n.elem * sizeof(Symbol *);
pars = memcpy(xmalloc(size), syms, size);
+ size = type.n.elem * sizeof(Type *);
+ type.p.pars = memcpy(xmalloc(size), types, size);
+ } else {
+ pars = NULL;
+ type.p.pars = NULL;
}
push(dp, FTN, type.n.elem, type.p.pars, pars);
}