ref: b9081437c83b589ac0618b12c555bdbc9897279f
parent: f7b3cb04badaa5b42b9f0af83af837ab32b0336b
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
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);
}
--
⑨