shithub: scc

Download patch

ref: 603c00cd96823aedea6d257701d38ed060cfc127
parent: 4330a34e8c341d7981d376ec1ae9647318d9b113
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Mar 27 05:22:21 EDT 2017

[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.

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -17,6 +17,7 @@
 #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 @@
 		TINT  nelem;
 		Symbol *sym;
 		Type **tpars;
+		Symbol **pars;
 	} d [NR_DECLARATORS];
 };
 
@@ -40,9 +42,12 @@
 	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 @@
 	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 @@
 	}
 
 	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 @@
                      Type *type);
 
 static int
-krpars(Symbol *pars[], unsigned *nparsp)
+krpars(struct declarators *dp)
 {
 	Symbol *sym;
 	int toomany = 0;
@@ -368,7 +375,7 @@
 		}
 		if (npars < NR_FUNPARAM) {
 			++npars;
-			*pars++ = sym;
+			*dp->pars++ = sym;
 			continue;
 		}
 		if (!toomany)
@@ -375,23 +382,18 @@
 		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 @@
 
 	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 @@
 				toomany = 1;
 			} else {
 				npars++;
-				*pars++ = sym;
+				*dp->pars++ = sym;
 			}
 		}
 
@@ -457,8 +459,7 @@
 		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 @@
 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 @@
 		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 @@
 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,9 +923,9 @@
 		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);
 
@@ -930,7 +932,7 @@
 		while (pop(&stack, &dcl))
 			/* nothing */;
 		sym = (*fun)(&dcl);
-		if (funbody(sym, pars))
+		if (funbody(sym, dcl.pars))
 			return sym;
 	} while (rep && accept(','));
 
--- /dev/null
+++ b/tests/execute/0130-mulpars.c
@@ -1,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);
+}
--- 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