shithub: scc

Download patch

ref: b9081437c83b589ac0618b12c555bdbc9897279f
parent: f7b3cb04badaa5b42b9f0af83af837ab32b0336b
author: Roberto E. Vargas Caballero <[email protected]>
date: Sat Sep 26 08:36:59 EDT 2015

Improve error recovery in argument parsing

--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -116,18 +116,6 @@
 	push(dp, ARY, n);
 }
 
-static void
-newpar(Type *fun, Type *par)
-{
-	TINT n = fun->n.elem;
-
-	if (n == NR_FUNPARAM)
-		error("too much parameters in function definition");
-	fun->p.pars = xrealloc(fun->p.pars, ++n * sizeof(Type *));
-	fun->p.pars[n-1] = par;
-	fun->n.elem = n;
-}
-
 static Symbol *
 parameter(struct decl *dcl)
 {
@@ -138,9 +126,6 @@
 
 	sym->type = tp;
 
-	if (n == -1)
-		error("'void' must be the only parameter");
-
 	switch (dcl->sclass) {
 	case STATIC:
 	case EXTERN:
@@ -157,26 +142,30 @@
 
 	switch (tp->op) {
 	case VOID:
-		if (n != 0)
-			error("incorrect void parameter");
-		if (dcl->sclass)
-			error("void as unique parameter may not be qualified");
+		if (n != 0) {
+			errorp("incorrect void parameter");
+			return NULL;
+		}
 		funtp->n.elem = -1;
+		if (dcl->sclass)
+			errorp("void as unique parameter may not be qualified");
 		return NULL;
 	case ARY:
 		tp = mktype(tp->type, PTR, 0, NULL);
 		break;
 	case FTN:
-		error("incorrect function type for a function parameter");
+		errorp("incorrect function type for a function parameter");
+		return NULL;
 	}
 
 	if (name) {
-		if ((sym = install(NS_IDEN, sym)) == NULL)
-			error("redefinition of parameter '%s'", name);
+		if ((sym = install(NS_IDEN, sym)) == NULL) {
+			errorp("redefinition of parameter '%s'", name);
+			return NULL;
+		}
 	}
 	sym->type = tp;
 	sym->flags |= ISUSED;    /* avoid non used warnings in prototypes */
-	newpar(funtp, tp);
 
 	return sym;
 }
@@ -189,35 +178,62 @@
 static void
 fundcl(struct declarators *dp)
 {
-	Type type;
-	Symbol *syms[NR_FUNPARAM], **sp = syms;
+	Type type, *types[NR_FUNPARAM], *tp;
+	Symbol *syms[NR_FUNPARAM], *sym;
 	TINT size;
-	Symbol *pars = NULL;
+	Symbol *pars;
+	int toomany = 0, toovoid = 0;
 
 	pushctx();
 	expect('(');
 	type.n.elem = 0;
-	type.p.pars = NULL;
 
-	if (accept(')')) {
-		newpar(&type, ellipsistype);
-		*sp++ = NULL;
-	} else {
-		do {
-			if (!accept(ELLIPSIS)) {
-				*sp++ = dodcl(0, parameter, NS_IDEN, &type);
-			} else {
-				newpar(&type, ellipsistype);
-				*sp++ = NULL;
-				break;
-			}
-		} while (accept(','));
-
-		expect(')');
+	if (yytoken == ')') {
+		++type.n.elem;
+		syms[0] = NULL;
+		types[0] = ellipsistype;
+		goto end_params;
 	}
-	if (type.n.elem != -1) {
+	do {
+		if (type.n.elem == -1) {
+			if (!toovoid)
+				errorp("'void' must be the only parameter");
+			toovoid = 1;
+		}
+		if (!accept(ELLIPSIS)) {
+			sym = dodcl(0, parameter, NS_IDEN, &type);
+			if (!sym)
+				continue;
+			tp = sym->type;
+		} else {
+			if (type.n.elem == 0)
+				errorp("a named argument is requiered before '...'");
+			tp = ellipsistype;
+			sym = NULL;
+		}
+		if (type.n.elem == NR_FUNPARAM) {
+			if (toomany)
+				continue;
+			errorp("too much parameters in function definition");
+			toomany = 1;
+		} else if (type.n.elem >= 0) {
+			syms[type.n.elem] = sym;
+			types[type.n.elem] = tp;
+			++type.n.elem;
+		}
+	} while (tp != ellipsistype && accept(','));
+
+end_params:
+	expect(')');
+
+	if (type.n.elem > 0) {
 		size = type.n.elem * sizeof(Symbol *);
 		pars = memcpy(xmalloc(size), syms, size);
+		size = type.n.elem * sizeof(Type *);
+		type.p.pars = memcpy(xmalloc(size), types, size);
+	} else {
+		pars = NULL;
+		type.p.pars = NULL;
 	}
 	push(dp, FTN, type.n.elem, type.p.pars, pars);
 }