scc

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

commit c6dd2dacda6c093f1a7d3c9786f64f4294e390a1
parent c8e766539a06923004070ddbfc00071eba596004
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 27 Mar 2017 09:22:21 +0200

[cc1] Support nested parameter declarations

The code was written in a way that there was possible only one
list of parameters, which was totally wrong, since it is
possible to have pointers to functions that return pointers
to other functions.

Diffstat:
Mcc1/decl.c | 52+++++++++++++++++++++++++++-------------------------
Atests/execute/0130-mulpars.c | 23+++++++++++++++++++++++
Mtests/execute/scc-tests.lst | 1+
3 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/cc1/decl.c b/cc1/decl.c @@ -17,6 +17,7 @@ static char sccsid[] = "@(#) ./cc1/decl.c"; #define NOQUIET 0 #define NR_DCL_TYP (NR_DECLARATORS+NR_FUNPARAM) +#define NR_DCL_SYM (NR_DECLARATORS+NR_FUNPARAM+1) struct declarators { unsigned nr; @@ -30,6 +31,7 @@ struct declarators { TINT nelem; Symbol *sym; Type **tpars; + Symbol **pars; } d [NR_DECLARATORS]; }; @@ -40,9 +42,12 @@ struct decl { Symbol *sym; Type *type; Type *parent; + Symbol **pars; + Symbol *bufpars[NR_DCL_SYM]; Type *buftpars[NR_DCL_TYP]; }; + static void endfundcl(Type *tp, Symbol **pars) { @@ -79,6 +84,7 @@ push(struct declarators *dp, int op, ...) case FTN: p->nelem = va_arg(va, unsigned); p->tpars = va_arg(va, Type **); + p->pars = va_arg(va, Symbol **); break; case IDEN: p->sym = va_arg(va, Symbol *); @@ -102,7 +108,8 @@ pop(struct declarators *dp, struct decl *dcl) } if (dcl->type->op == FTN) - endfundcl(dcl->type, dp->pars); + endfundcl(dcl->type, dcl->pars); + dcl->pars = p->pars; dcl->type = mktype(dcl->type, p->op, p->nelem, p->tpars); return 1; @@ -351,7 +358,7 @@ static Symbol *dodcl(int rep, Type *type); static int -krpars(Symbol *pars[], unsigned *nparsp) +krpars(struct declarators *dp) { Symbol *sym; int toomany = 0; @@ -368,30 +375,25 @@ krpars(Symbol *pars[], unsigned *nparsp) } if (npars < NR_FUNPARAM) { ++npars; - *pars++ = sym; + *dp->pars++ = sym; continue; } if (!toomany) toomany = 1; } while (accept(',')); - *nparsp = npars; return toomany; } -static void -krfun(struct declarators *dp, - Symbol *pars[], unsigned *ntypep, unsigned *nparsp) +static unsigned +krfun(struct declarators *dp) { int toomany = 0; if (yytoken != ')') - toomany = krpars(pars, nparsp); - else - *nparsp = 0; + toomany = krpars(dp); - *ntypep = 1; if (dp->nr_types == NR_DCL_TYP) { toomany = 1; } else { @@ -401,11 +403,11 @@ krfun(struct declarators *dp, if (toomany) errorp("too many parameters in function definition"); + return 1; } -static void -ansifun(struct declarators *dp, - Symbol *pars[], unsigned *ntypep, unsigned *nparsp) +static unsigned +ansifun(struct declarators *dp) { Symbol *sym; unsigned npars, ntype, toomany, distoomany, voidpar; @@ -437,7 +439,7 @@ ansifun(struct declarators *dp, toomany = 1; } else { npars++; - *pars++ = sym; + *dp->pars++ = sym; } } @@ -457,8 +459,7 @@ ansifun(struct declarators *dp, errorp("too many parameters in function definition"); if (voidpar && ntype > 1) errorp("'void' must be the only parameter"); - *ntypep = ntype; - *nparsp = npars; + return ntype; } static int @@ -525,8 +526,9 @@ static void fundcl(struct declarators *dp) { Type **types = dp->tpars; - unsigned npars, ntypes, typefun; - void (*fun)(struct declarators *, Symbol **, unsigned *, unsigned *); + unsigned ntypes, typefun; + Symbol **pars = dp->pars; + unsigned (*fun)(struct declarators *); pushctx(); expect('('); @@ -537,11 +539,11 @@ fundcl(struct declarators *dp) typefun = FTN; fun = ansifun; } - (*fun)(dp, dp->pars, &ntypes, &npars); - dp->pars[npars] = NULL; + ntypes = (*fun)(dp); + *dp->pars++= NULL; expect(')'); - push(dp, typefun, ntypes, types); + push(dp, typefun, ntypes, types, pars); } static void declarator(struct declarators *dp); @@ -908,7 +910,7 @@ field(struct decl *dcl) static Symbol * dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) { - Symbol *sym, *pars[NR_FUNPARAM+1]; + Symbol *sym; Type *base; struct decl dcl; struct declarators stack; @@ -921,16 +923,16 @@ dodcl(int rep, Symbol *(*fun)(struct decl *), unsigned ns, Type *parent) dcl.type = base; stack.nr_types = stack.nr = 0; stack.tpars = dcl.buftpars; + stack.pars = dcl.bufpars; stack.dcl = &dcl; stack.ns = ns; - stack.pars = pars; declarator(&stack); while (pop(&stack, &dcl)) /* nothing */; sym = (*fun)(&dcl); - if (funbody(sym, pars)) + if (funbody(sym, dcl.pars)) return sym; } while (rep && accept(',')); diff --git a/tests/execute/0130-mulpars.c b/tests/execute/0130-mulpars.c @@ -0,0 +1,23 @@ + +int +f2(int c, int b) +{ + return c - b; +} + +int (* +f1(int a, int b))(int c, int b) +{ + if (a != b) + return f2; + return 0; +} + +int +main() +{ + int (* (*p)(int a, int b))(int c, int d) = f1; + + + return (*(*p)(0, 2))(2, 2); +} diff --git a/tests/execute/scc-tests.lst b/tests/execute/scc-tests.lst @@ -120,3 +120,4 @@ 0127-doublecte.c [TODO] 0128-kr_names.c 0129-initi.c [TODO] +0130-mulpars.c