shithub: mc

Download patch

ref: 1fc981b2ef099974206af6ad0242c38ccdffb02e
parent: 46d4b4ea638d8aefc0fb6b4f32413acdc20e2ce7
author: Ori Bernstein <ori@eigenstate.org>
date: Fri Mar 10 17:11:45 EST 2017

Fix labels in nested functions.

	We used to keep a list of labels seen in a function so we
	could transfer them to the function scope when we finished
	parsing. This was incorrect because nested functions would
	collect all the labels from the enclosing scope.

	We now keep a stack.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -19,8 +19,11 @@
 
 
 Stab *curscope;
-static Node **lbls;
-static size_t nlbls;
+#define LBLSTKSZ 64
+static Node **lbls[LBLSTKSZ];
+static size_t nlbls[LBLSTKSZ];
+/* the first time we see a label, we increment to 0 */
+static int lbldepth = -1;
 
 void yyerror(const char *s);
 int yylex(void);
@@ -132,7 +135,7 @@
 %type <tylist> typelist typarams optauxtypes
 %type <nodelist> typaramlist
 
-%type <tok> asnop cmpop addop mulop shiftop optident
+%type <tok> asnop cmpop addop mulop shiftop optident obrace
 
 %type <tydef> tydef pkgtydef typeid
 %type <trait> traitdef
@@ -806,29 +809,39 @@
 	}
 	;
 
-funclit : Tobrace params Tendln blkbody Tcbrace {
+obrace	: Tobrace {
+		assert(lbldepth < LBLSTKSZ);
+		lbldepth++;
+	}
+	;
+
+funclit : obrace params Tendln blkbody Tcbrace {
 		size_t i;
 		Node *fn, *lit;
 
 		$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);
 		fn = $$->lit.fnval;
-		for (i = 0; i < nlbls; i++) {
-			lit = lbls[i]->expr.args[0];
-			putlbl(fn->func.scope, lit->lit.lblname, lbls[i]);
+		for (i = 0; i < nlbls[lbldepth]; i++) {
+			lit = lbls[lbldepth][i]->expr.args[0];
+			putlbl(fn->func.scope, lit->lit.lblname, lbls[lbldepth][i]);
 		}
-		lfree(&lbls, &nlbls);
+		lfree(&lbls[lbldepth], &nlbls[lbldepth]);
+		assert(lbldepth >= 0);
+		lbldepth--;
 	}
-	| Tobrace params Tret type Tendln blkbody Tcbrace {
+	| obrace params Tret type Tendln blkbody Tcbrace {
 		size_t i;
 		Node *fn, *lit;
 
 		$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);
 		fn = $$->lit.fnval;
-		for (i = 0; i < nlbls; i++) {
-			lit = lbls[i]->expr.args[0];
-			putlbl(fn->func.scope, lit->lit.lblname, lbls[i]);
+		for (i = 0; i < nlbls[lbldepth]; i++) {
+			lit = lbls[lbldepth][i]->expr.args[0];
+			putlbl(fn->func.scope, lit->lit.lblname, lbls[lbldepth][i]);
 		}
-		lfree(&lbls, &nlbls);
+		lfree(&lbls[lbldepth], &nlbls[lbldepth]);
+		assert(lbldepth >= 0);
+		lbldepth--;
 	}
 	;
 
@@ -1024,7 +1037,7 @@
 		genlblstr(buf, sizeof buf, $2->id);
 		$$ = mklbl($2->loc, buf);
 		$$->expr.args[0]->lit.lblname = strdup($2->id);
-		lappend(&lbls, &nlbls, $$);
+		lappend(&lbls[lbldepth], &nlbls[lbldepth], $$);
 	}
 	;