scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit b9081437c83b589ac0618b12c555bdbc9897279f
parent f7b3cb04badaa5b42b9f0af83af837ab32b0336b
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 26 Sep 2015 12:36:59 +0200

Improve error recovery in argument parsing

Diffstat:
Mcc1/decl.c | 102++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
1 file changed, 59 insertions(+), 43 deletions(-)

diff --git a/cc1/decl.c b/cc1/decl.c @@ -116,18 +116,6 @@ arydcl(struct declarators *dp) 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 @@ parameter(struct decl *dcl) sym->type = tp; - if (n == -1) - error("'void' must be the only parameter"); - switch (dcl->sclass) { case STATIC: case EXTERN: @@ -157,26 +142,30 @@ parameter(struct decl *dcl) 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 Symbol *dodcl(int rep, 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); }