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:
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