shithub: scc

Download patch

ref: ab74e508b10e6bdf39ae71e204bf91642257d689
parent: a0862978b0a1d5c876db7839cc6905b749291640
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Aug 7 16:28:12 EDT 2015

Fix fundcl()

Fundcl() has to take the decision when it is needed the parameter
context or not, and the only way is to check if the next token
is a allowed one in a function definition. Ideally the
context should be poped before calling expect(), but we know
that after a parameter list cannot go a identifier, so it is
not a problem.

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -91,34 +91,43 @@
 	Type type = {.n = {.elem = -1}, .pars = NULL};
 	Symbol *syms[NR_FUNPARAM], **sp;
 	size_t size;
+	void *p;
 
 	pushctx();
 	expect('(');
 
-	if (accept(')'))
-		goto nopars;
+	if (accept(')')) {
+		dp = queue(dp, FTN, type.n.elem, type.pars);
+	} else {
+		type.n.elem = 0;
+		sp = syms;
+		do
+			*sp++ = dodcl(0, parameter, NS_IDEN, &type);
+		while (accept(','));
 
-	type.n.elem = 0;
-	sp = syms;
-	do
-		*sp++ = dodcl(0, parameter, NS_IDEN, &type);
-	while (accept(','));
+		expect(')');
 
-	if (ahead() != '{')
-		goto nopars;
+		dp = queue(dp, FTN, type.n.elem, type.pars);
+		if (type.n.elem != -1) {
+			size = type.n.elem * sizeof(Symbol *);
+			p = memcpy(xmalloc(size), syms, size);
+			dp = queue(dp, PARS, 0, p);
+		}
+	}
 
-	expect(')');
-
-	dp = queue(dp, FTN, type.n.elem, type.pars);
-	if (type.n.elem != -1) {
-		size = type.n.elem * sizeof(Symbol *);
-		dp = queue(dp, PARS, 0, memcpy(xmalloc(size), syms, size));
+	switch (yytoken) {
+	default:
+		/* This is not a function */
+		popctx();
+	case '{':
+	case TYPEIDEN:
+	case TYPE:
+	case TQUALIFIER:
+	case SCLASS:
+		/* This can be a function (K&R included) */
+		break;
 	}
 	return dp;
-
-nopars:
-	expect(')');
-	return queue(dp, FTN, type.n.elem, type.pars);
 }
 
 static struct dcldata *declarator0(struct dcldata *dp, unsigned ns);
@@ -457,9 +466,7 @@
 		warn("empty declaration");
 		return;
 	}
-	if (sym->type->op == FTN) {
-		popctx();
-	} else {
+	if (sym->type->op != FTN) {
 		if (!sclass)
 			sym->flags |= ISAUTO;
 		if (accept('='))