scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit ad2e30089260ee4dc4bb7bd674ab65516ffee854
parent 4626414db8c5ae6f8b65054d74465626be2a4fc1
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 13 Feb 2017 16:58:29 +0100

[cc1] Add warnings in builtin_va_start()

There are a lot of strange conditions in va_start()
that should be informed as warnings to the user,
because any of them can generate wrong code in
some implementations/architectures.

Diffstat:
Mcc1/builtin.c | 26++++++++++++++++++++++----
Mcc1/code.c | 2--
Mcc1/decl.c | 2++
3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/cc1/builtin.c b/cc1/builtin.c @@ -18,7 +18,7 @@ builtin_va_arg(Symbol *sym) if (!valid_va_list(ap->type)) { errorp("incorrect parameters for va_arg"); - return constnode(zero); + goto error; } if (tp == booltype || tp == chartype || tp == uchartype || tp == schartype || @@ -30,6 +30,9 @@ builtin_va_arg(Symbol *sym) np = node(OBUILTIN, tp, ap, NULL); np->sym = sym; return np; + +error: + return constnode(zero); } static Node * @@ -55,16 +58,31 @@ static Node * builtin_va_start(Symbol *sym) { Node *np, *ap, *last; + Symbol **p, *lastsym; + Type *tp; ap = assign(); expect(','); if (yytoken != IDEN) goto error; - last = varnode(yylval.sym); + lastsym = yylval.sym; + last = varnode(lastsym); next(); - if (!valid_va_list(ap->type)) - goto error; + if (!valid_va_list(ap->type) || !(lastsym->flags&SDECLARED)) + goto error; + + for (p = curfun->u.pars; p && *p != lastsym; ++p) + /* nothing */; + if (!p || *p == NULL || p[1] == NULL || p[1]->type != ellipsistype) + warn("second parameter of 'va_start' not last named argument"); + + tp = last->type; + if (tp == booltype || + tp == chartype || tp == uchartype || tp == schartype || + tp == shortype || tp == ushortype) { + warn("last parameter before '...' must not be bool, char or short"); + } np = node(OBUILTIN, voidtype, ap, last); np->sym = sym; diff --git a/cc1/code.c b/cc1/code.c @@ -470,8 +470,6 @@ emitfun(unsigned op, void *arg) for (sp = sym->u.pars; sp && *sp; ++sp) emit(ODECL, *sp); fputs("\\\n", outfp); - free(sym->u.pars); - sym->u.pars = NULL; } static void diff --git a/cc1/decl.c b/cc1/decl.c @@ -901,6 +901,8 @@ decl(void) compound(NULL, NULL, NULL); popctx(); emit(OEFUN, NULL); + free(sym->u.pars); + sym->u.pars = NULL; flushtypes(); curfun = ocurfun; }