cmd/gc: implement new return requirements

Fixes #65.

R=ken2
CC=golang-dev
https://golang.org/cl/7441049
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index f86c152..7e5e1b7 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -268,6 +268,7 @@
 	uchar	addrtaken;	// address taken, even if not moved to heap
 	uchar	dupok;	// duplicate definitions ok (for func)
 	schar	likely; // likeliness of if statement
+	uchar	hasbreak;	// has break statement
 
 	// most nodes
 	Type*	type;
@@ -1363,6 +1364,7 @@
 void	typechecklist(NodeList *l, int top);
 Node*	typecheckdef(Node *n);
 void	copytype(Node *n, Type *t);
+void	checkreturn(Node*);
 void	queuemethod(Node *n);
 
 /*
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 794961e..a12da56 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -536,7 +536,10 @@
 	}
 	stmt_list '}'
 	{
-		$$ = liststmt($3);
+		if($3 == nil)
+			$$ = nod(OEMPTY, N, N);
+		else
+			$$ = liststmt($3);
 		popdcl();
 	}
 
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 68ae686..118a0d7 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -376,6 +376,7 @@
 			curfn = l->n;
 			saveerrors();
 			typechecklist(l->n->nbody, Etop);
+			checkreturn(l->n);
 			if(nerrors != 0)
 				l->n->nbody = nil;  // type errors; do not compile
 		}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index fbab85d..47e555f 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -3144,3 +3144,148 @@
 	}
 	return 0;
 }
+
+static void	markbreaklist(NodeList*, Node*);
+
+static void
+markbreak(Node *n, Node *implicit)
+{
+	Label *lab;
+
+	if(n == N)
+		return;
+
+	switch(n->op) {
+	case OBREAK:
+		if(n->left == N) {
+			if(implicit)
+				implicit->hasbreak = 1;
+		} else {
+			lab = n->left->sym->label;
+			if(lab != L)
+				lab->def->hasbreak = 1;
+		}
+		break;
+	
+	case OFOR:
+	case OSWITCH:
+	case OTYPESW:
+	case OSELECT:
+	case ORANGE:
+		implicit = n;
+		// fall through
+	
+	default:
+		markbreak(n->left, implicit);
+		markbreak(n->right, implicit);
+		markbreak(n->ntest, implicit);
+		markbreak(n->nincr, implicit);
+		markbreaklist(n->ninit, implicit);
+		markbreaklist(n->nbody, implicit);
+		markbreaklist(n->nelse, implicit);
+		markbreaklist(n->list, implicit);
+		markbreaklist(n->rlist, implicit);
+		break;
+	}
+}
+
+static void
+markbreaklist(NodeList *l, Node *implicit)
+{
+	Node *n;
+	Label *lab;
+
+	for(; l; l=l->next) {
+		n = l->n;
+		if(n->op == OLABEL && l->next && n->defn == l->next->n) {
+			switch(n->defn->op) {
+			case OFOR:
+			case OSWITCH:
+			case OTYPESW:
+			case OSELECT:
+			case ORANGE:
+				lab = mal(sizeof *lab);
+				lab->def = n->defn;
+				n->left->sym->label = lab;
+				markbreak(n->defn, n->defn);
+				n->left->sym->label = L;
+				l = l->next;
+				continue;
+			}
+		}
+		markbreak(n, implicit);
+	}
+}
+
+static int
+isterminating(NodeList *l, int top)
+{
+	int def;
+	Node *n;
+
+	if(l == nil)
+		return 0;
+	if(top) {
+		while(l->next && l->n->op != OLABEL)
+			l = l->next;
+		markbreaklist(l, nil);
+	}
+	while(l->next)
+		l = l->next;
+	n = l->n;
+
+	if(n == N)
+		return 0;
+
+	switch(n->op) {
+	// NOTE: OLABEL is treated as a separate statement,
+	// not a separate prefix, so skipping to the last statement
+	// in the block handles the labeled statement case by
+	// skipping over the label. No case OLABEL here.
+
+	case OBLOCK:
+		return isterminating(n->list, 0);
+
+	case OGOTO:
+	case ORETURN:
+	case OPANIC:
+	case OXFALL:
+		return 1;
+
+	case OFOR:
+		if(n->ntest != N)
+			return 0;
+		if(n->hasbreak)
+			return 0;
+		return 1;
+
+	case OIF:
+		return isterminating(n->nbody, 0) && isterminating(n->nelse, 0);
+
+	case OSWITCH:
+	case OTYPESW:
+	case OSELECT:
+		if(n->hasbreak)
+			return 0;
+		def = 0;
+		for(l=n->list; l; l=l->next) {
+			if(!isterminating(l->n->nbody, 0))
+				return 0;
+			if(l->n->list == nil) // default
+				def = 1;
+		}
+		if(n->op != OSELECT && !def)
+			return 0;
+		return 1;
+	}
+	
+	return 0;
+}
+
+void
+checkreturn(Node *fn)
+{
+	if(fn->type->outtuple && fn->nbody != nil)
+		if(!isterminating(fn->nbody, 1))
+			yyerrorl(fn->endlineno, "missing return at end of function");
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index de2105e..831917f 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -29,40 +29,6 @@
 static	int	bounded(Node*, int64);
 static	Mpint	mpzero;
 
-// can this code branch reach the end
-// without an unconditional RETURN
-// this is hard, so it is conservative
-static int
-walkret(NodeList *l)
-{
-	Node *n;
-
-loop:
-	while(l && l->next)
-		l = l->next;
-	if(l == nil)
-		return 1;
-
-	// at this point, we have the last
-	// statement of the function
-	n = l->n;
-	switch(n->op) {
-	case OBLOCK:
-		l = n->list;
-		goto loop;
-
-	case OGOTO:
-	case ORETURN:
-	case OPANIC:
-		return 0;
-		break;
-	}
-
-	// all other statements
-	// will flow to the end
-	return 1;
-}
-
 void
 walk(Node *fn)
 {
@@ -76,9 +42,6 @@
 		snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
 		dumplist(s, curfn->nbody);
 	}
-	if(curfn->type->outtuple)
-		if(walkret(curfn->nbody))
-			yyerror("function ends without a return statement");
 
 	lno = lineno;
 
diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c
index 7517545..dee7939 100644
--- a/src/cmd/gc/y.tab.c
+++ b/src/cmd/gc/y.tab.c
@@ -662,35 +662,35 @@
      304,   308,   312,   318,   324,   330,   335,   339,   343,   349,
      355,   359,   363,   369,   373,   379,   380,   384,   390,   399,
      405,   423,   428,   440,   456,   461,   468,   488,   506,   515,
-     534,   533,   545,   544,   575,   578,   585,   584,   595,   601,
-     610,   621,   627,   630,   638,   637,   648,   654,   666,   670,
-     675,   665,   696,   695,   708,   711,   717,   720,   732,   736,
-     731,   754,   753,   769,   770,   774,   778,   782,   786,   790,
-     794,   798,   802,   806,   810,   814,   818,   822,   826,   830,
-     834,   838,   842,   847,   853,   854,   858,   869,   873,   877,
-     881,   886,   890,   900,   904,   909,   917,   921,   922,   933,
-     937,   941,   945,   949,   950,   956,   963,   969,   976,   979,
-     986,   992,  1009,  1016,  1017,  1024,  1025,  1044,  1045,  1048,
-    1051,  1055,  1066,  1075,  1081,  1084,  1087,  1094,  1095,  1101,
-    1116,  1124,  1136,  1141,  1147,  1148,  1149,  1150,  1151,  1152,
-    1158,  1159,  1160,  1161,  1167,  1168,  1169,  1170,  1171,  1177,
-    1178,  1181,  1184,  1185,  1186,  1187,  1188,  1191,  1192,  1205,
-    1209,  1214,  1219,  1224,  1228,  1229,  1232,  1238,  1245,  1251,
-    1258,  1264,  1275,  1289,  1318,  1358,  1383,  1401,  1410,  1413,
-    1421,  1425,  1429,  1436,  1442,  1447,  1459,  1462,  1472,  1473,
-    1479,  1480,  1486,  1490,  1496,  1497,  1503,  1507,  1513,  1536,
-    1541,  1547,  1553,  1560,  1569,  1578,  1593,  1599,  1604,  1608,
-    1615,  1628,  1629,  1635,  1641,  1644,  1648,  1654,  1657,  1666,
-    1669,  1670,  1674,  1675,  1681,  1682,  1683,  1684,  1685,  1687,
-    1686,  1701,  1706,  1710,  1714,  1718,  1722,  1727,  1746,  1752,
-    1760,  1764,  1770,  1774,  1780,  1784,  1790,  1794,  1803,  1807,
-    1811,  1815,  1821,  1824,  1832,  1833,  1835,  1836,  1839,  1842,
-    1845,  1848,  1851,  1854,  1857,  1860,  1863,  1866,  1869,  1872,
-    1875,  1878,  1884,  1888,  1892,  1896,  1900,  1904,  1924,  1931,
-    1942,  1943,  1944,  1947,  1948,  1951,  1955,  1965,  1969,  1973,
-    1977,  1981,  1985,  1989,  1995,  2001,  2009,  2017,  2023,  2030,
-    2046,  2064,  2068,  2074,  2077,  2080,  2084,  2094,  2098,  2113,
-    2121,  2122,  2134,  2135,  2138,  2142,  2148,  2152,  2158,  2162
+     534,   533,   548,   547,   578,   581,   588,   587,   598,   604,
+     613,   624,   630,   633,   641,   640,   651,   657,   669,   673,
+     678,   668,   699,   698,   711,   714,   720,   723,   735,   739,
+     734,   757,   756,   772,   773,   777,   781,   785,   789,   793,
+     797,   801,   805,   809,   813,   817,   821,   825,   829,   833,
+     837,   841,   845,   850,   856,   857,   861,   872,   876,   880,
+     884,   889,   893,   903,   907,   912,   920,   924,   925,   936,
+     940,   944,   948,   952,   953,   959,   966,   972,   979,   982,
+     989,   995,  1012,  1019,  1020,  1027,  1028,  1047,  1048,  1051,
+    1054,  1058,  1069,  1078,  1084,  1087,  1090,  1097,  1098,  1104,
+    1119,  1127,  1139,  1144,  1150,  1151,  1152,  1153,  1154,  1155,
+    1161,  1162,  1163,  1164,  1170,  1171,  1172,  1173,  1174,  1180,
+    1181,  1184,  1187,  1188,  1189,  1190,  1191,  1194,  1195,  1208,
+    1212,  1217,  1222,  1227,  1231,  1232,  1235,  1241,  1248,  1254,
+    1261,  1267,  1278,  1292,  1321,  1361,  1386,  1404,  1413,  1416,
+    1424,  1428,  1432,  1439,  1445,  1450,  1462,  1465,  1475,  1476,
+    1482,  1483,  1489,  1493,  1499,  1500,  1506,  1510,  1516,  1539,
+    1544,  1550,  1556,  1563,  1572,  1581,  1596,  1602,  1607,  1611,
+    1618,  1631,  1632,  1638,  1644,  1647,  1651,  1657,  1660,  1669,
+    1672,  1673,  1677,  1678,  1684,  1685,  1686,  1687,  1688,  1690,
+    1689,  1704,  1709,  1713,  1717,  1721,  1725,  1730,  1749,  1755,
+    1763,  1767,  1773,  1777,  1783,  1787,  1793,  1797,  1806,  1810,
+    1814,  1818,  1824,  1827,  1835,  1836,  1838,  1839,  1842,  1845,
+    1848,  1851,  1854,  1857,  1860,  1863,  1866,  1869,  1872,  1875,
+    1878,  1881,  1887,  1891,  1895,  1899,  1903,  1907,  1927,  1934,
+    1945,  1946,  1947,  1950,  1951,  1954,  1958,  1968,  1972,  1976,
+    1980,  1984,  1988,  1992,  1998,  2004,  2012,  2020,  2026,  2033,
+    2049,  2067,  2071,  2077,  2080,  2083,  2087,  2097,  2101,  2116,
+    2124,  2125,  2137,  2138,  2141,  2145,  2151,  2155,  2161,  2165
 };
 #endif
 
@@ -2867,13 +2867,16 @@
   case 61:
 #line 538 "go.y"
     {
-		(yyval.node) = liststmt((yyvsp[(3) - (4)].list));
+		if((yyvsp[(3) - (4)].list) == nil)
+			(yyval.node) = nod(OEMPTY, N, N);
+		else
+			(yyval.node) = liststmt((yyvsp[(3) - (4)].list));
 		popdcl();
 	}
     break;
 
   case 62:
-#line 545 "go.y"
+#line 548 "go.y"
     {
 		// If the last token read by the lexer was consumed
 		// as part of the case, clear it (parser has cleared yychar).
@@ -2886,7 +2889,7 @@
     break;
 
   case 63:
-#line 555 "go.y"
+#line 558 "go.y"
     {
 		int last;
 
@@ -2908,28 +2911,28 @@
     break;
 
   case 64:
-#line 575 "go.y"
+#line 578 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 65:
-#line 579 "go.y"
+#line 582 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node));
 	}
     break;
 
   case 66:
-#line 585 "go.y"
+#line 588 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 67:
-#line 589 "go.y"
+#line 592 "go.y"
     {
 		(yyval.list) = (yyvsp[(3) - (4)].list);
 		popdcl();
@@ -2937,7 +2940,7 @@
     break;
 
   case 68:
-#line 596 "go.y"
+#line 599 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2946,7 +2949,7 @@
     break;
 
   case 69:
-#line 602 "go.y"
+#line 605 "go.y"
     {
 		(yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node));
 		(yyval.node)->list = (yyvsp[(1) - (4)].list);
@@ -2956,7 +2959,7 @@
     break;
 
   case 70:
-#line 611 "go.y"
+#line 614 "go.y"
     {
 		// init ; test ; incr
 		if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0)
@@ -2970,7 +2973,7 @@
     break;
 
   case 71:
-#line 622 "go.y"
+#line 625 "go.y"
     {
 		// normal test
 		(yyval.node) = nod(OFOR, N, N);
@@ -2979,7 +2982,7 @@
     break;
 
   case 73:
-#line 631 "go.y"
+#line 634 "go.y"
     {
 		(yyval.node) = (yyvsp[(1) - (2)].node);
 		(yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list));
@@ -2987,14 +2990,14 @@
     break;
 
   case 74:
-#line 638 "go.y"
+#line 641 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 75:
-#line 642 "go.y"
+#line 645 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (3)].node);
 		popdcl();
@@ -3002,7 +3005,7 @@
     break;
 
   case 76:
-#line 649 "go.y"
+#line 652 "go.y"
     {
 		// test
 		(yyval.node) = nod(OIF, N, N);
@@ -3011,7 +3014,7 @@
     break;
 
   case 77:
-#line 655 "go.y"
+#line 658 "go.y"
     {
 		// init ; test
 		(yyval.node) = nod(OIF, N, N);
@@ -3022,14 +3025,14 @@
     break;
 
   case 78:
-#line 666 "go.y"
+#line 669 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 79:
-#line 670 "go.y"
+#line 673 "go.y"
     {
 		if((yyvsp[(3) - (3)].node)->ntest == N)
 			yyerror("missing condition in if statement");
@@ -3037,14 +3040,14 @@
     break;
 
   case 80:
-#line 675 "go.y"
+#line 678 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list);
 	}
     break;
 
   case 81:
-#line 679 "go.y"
+#line 682 "go.y"
     {
 		Node *n;
 		NodeList *nn;
@@ -3062,14 +3065,14 @@
     break;
 
   case 82:
-#line 696 "go.y"
+#line 699 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 83:
-#line 700 "go.y"
+#line 703 "go.y"
     {
 		if((yyvsp[(4) - (5)].node)->ntest == N)
 			yyerror("missing condition in if statement");
@@ -3079,28 +3082,28 @@
     break;
 
   case 84:
-#line 708 "go.y"
+#line 711 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 85:
-#line 712 "go.y"
+#line 715 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list));
 	}
     break;
 
   case 86:
-#line 717 "go.y"
+#line 720 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 87:
-#line 721 "go.y"
+#line 724 "go.y"
     {
 		NodeList *node;
 		
@@ -3112,14 +3115,14 @@
     break;
 
   case 88:
-#line 732 "go.y"
+#line 735 "go.y"
     {
 		markdcl();
 	}
     break;
 
   case 89:
-#line 736 "go.y"
+#line 739 "go.y"
     {
 		Node *n;
 		n = (yyvsp[(3) - (3)].node)->ntest;
@@ -3130,7 +3133,7 @@
     break;
 
   case 90:
-#line 744 "go.y"
+#line 747 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (7)].node);
 		(yyval.node)->op = OSWITCH;
@@ -3141,14 +3144,14 @@
     break;
 
   case 91:
-#line 754 "go.y"
+#line 757 "go.y"
     {
 		typesw = nod(OXXX, typesw, N);
 	}
     break;
 
   case 92:
-#line 758 "go.y"
+#line 761 "go.y"
     {
 		(yyval.node) = nod(OSELECT, N, N);
 		(yyval.node)->lineno = typesw->lineno;
@@ -3158,154 +3161,154 @@
     break;
 
   case 94:
-#line 771 "go.y"
+#line 774 "go.y"
     {
 		(yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 95:
-#line 775 "go.y"
+#line 778 "go.y"
     {
 		(yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 96:
-#line 779 "go.y"
+#line 782 "go.y"
     {
 		(yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 97:
-#line 783 "go.y"
+#line 786 "go.y"
     {
 		(yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 98:
-#line 787 "go.y"
+#line 790 "go.y"
     {
 		(yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 99:
-#line 791 "go.y"
+#line 794 "go.y"
     {
 		(yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 100:
-#line 795 "go.y"
+#line 798 "go.y"
     {
 		(yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 101:
-#line 799 "go.y"
+#line 802 "go.y"
     {
 		(yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 102:
-#line 803 "go.y"
+#line 806 "go.y"
     {
 		(yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 103:
-#line 807 "go.y"
+#line 810 "go.y"
     {
 		(yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 104:
-#line 811 "go.y"
+#line 814 "go.y"
     {
 		(yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 105:
-#line 815 "go.y"
+#line 818 "go.y"
     {
 		(yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 106:
-#line 819 "go.y"
+#line 822 "go.y"
     {
 		(yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 107:
-#line 823 "go.y"
+#line 826 "go.y"
     {
 		(yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 108:
-#line 827 "go.y"
+#line 830 "go.y"
     {
 		(yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 109:
-#line 831 "go.y"
+#line 834 "go.y"
     {
 		(yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 110:
-#line 835 "go.y"
+#line 838 "go.y"
     {
 		(yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 111:
-#line 839 "go.y"
+#line 842 "go.y"
     {
 		(yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 112:
-#line 843 "go.y"
+#line 846 "go.y"
     {
 		(yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 113:
-#line 848 "go.y"
+#line 851 "go.y"
     {
 		(yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 115:
-#line 855 "go.y"
+#line 858 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 116:
-#line 859 "go.y"
+#line 862 "go.y"
     {
 		if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) {
 			// Special case for &T{...}: turn into (*T){...}.
@@ -3319,28 +3322,28 @@
     break;
 
   case 117:
-#line 870 "go.y"
+#line 873 "go.y"
     {
 		(yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 118:
-#line 874 "go.y"
+#line 877 "go.y"
     {
 		(yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 119:
-#line 878 "go.y"
+#line 881 "go.y"
     {
 		(yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 120:
-#line 882 "go.y"
+#line 885 "go.y"
     {
 		yyerror("the bitwise complement operator is ^");
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
@@ -3348,28 +3351,28 @@
     break;
 
   case 121:
-#line 887 "go.y"
+#line 890 "go.y"
     {
 		(yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 122:
-#line 891 "go.y"
+#line 894 "go.y"
     {
 		(yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 123:
-#line 901 "go.y"
+#line 904 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N);
 	}
     break;
 
   case 124:
-#line 905 "go.y"
+#line 908 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3377,7 +3380,7 @@
     break;
 
   case 125:
-#line 910 "go.y"
+#line 913 "go.y"
     {
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N);
 		(yyval.node)->list = (yyvsp[(3) - (6)].list);
@@ -3386,14 +3389,14 @@
     break;
 
   case 126:
-#line 918 "go.y"
+#line 921 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
   case 128:
-#line 923 "go.y"
+#line 926 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3407,35 +3410,35 @@
     break;
 
   case 129:
-#line 934 "go.y"
+#line 937 "go.y"
     {
 		(yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node));
 	}
     break;
 
   case 130:
-#line 938 "go.y"
+#line 941 "go.y"
     {
 		(yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node));
 	}
     break;
 
   case 131:
-#line 942 "go.y"
+#line 945 "go.y"
     {
 		(yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
 	}
     break;
 
   case 132:
-#line 946 "go.y"
+#line 949 "go.y"
     {
 		(yyval.node) = nod(OSLICE, (yyvsp[(1) - (6)].node), nod(OKEY, (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node)));
 	}
     break;
 
   case 134:
-#line 951 "go.y"
+#line 954 "go.y"
     {
 		// conversion
 		(yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N);
@@ -3444,7 +3447,7 @@
     break;
 
   case 135:
-#line 957 "go.y"
+#line 960 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3454,7 +3457,7 @@
     break;
 
   case 136:
-#line 964 "go.y"
+#line 967 "go.y"
     {
 		(yyval.node) = (yyvsp[(3) - (5)].node);
 		(yyval.node)->right = (yyvsp[(1) - (5)].node);
@@ -3463,7 +3466,7 @@
     break;
 
   case 137:
-#line 970 "go.y"
+#line 973 "go.y"
     {
 		yyerror("cannot parenthesize type in composite literal");
 		(yyval.node) = (yyvsp[(5) - (7)].node);
@@ -3473,7 +3476,7 @@
     break;
 
   case 139:
-#line 979 "go.y"
+#line 982 "go.y"
     {
 		// composite expression.
 		// make node early so we get the right line number.
@@ -3482,14 +3485,14 @@
     break;
 
   case 140:
-#line 987 "go.y"
+#line 990 "go.y"
     {
 		(yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 141:
-#line 993 "go.y"
+#line 996 "go.y"
     {
 		// These nodes do not carry line numbers.
 		// Since a composite literal commonly spans several lines,
@@ -3509,7 +3512,7 @@
     break;
 
   case 142:
-#line 1010 "go.y"
+#line 1013 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (4)].node);
 		(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3517,7 +3520,7 @@
     break;
 
   case 144:
-#line 1018 "go.y"
+#line 1021 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (4)].node);
 		(yyval.node)->list = (yyvsp[(3) - (4)].list);
@@ -3525,7 +3528,7 @@
     break;
 
   case 146:
-#line 1026 "go.y"
+#line 1029 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		
@@ -3545,21 +3548,21 @@
     break;
 
   case 150:
-#line 1052 "go.y"
+#line 1055 "go.y"
     {
 		(yyval.i) = LBODY;
 	}
     break;
 
   case 151:
-#line 1056 "go.y"
+#line 1059 "go.y"
     {
 		(yyval.i) = '{';
 	}
     break;
 
   case 152:
-#line 1067 "go.y"
+#line 1070 "go.y"
     {
 		if((yyvsp[(1) - (1)].sym) == S)
 			(yyval.node) = N;
@@ -3569,21 +3572,21 @@
     break;
 
   case 153:
-#line 1076 "go.y"
+#line 1079 "go.y"
     {
 		(yyval.node) = dclname((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 154:
-#line 1081 "go.y"
+#line 1084 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 156:
-#line 1088 "go.y"
+#line 1091 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		// during imports, unqualified non-exported identifiers are from builtinpkg
@@ -3593,14 +3596,14 @@
     break;
 
   case 158:
-#line 1096 "go.y"
+#line 1099 "go.y"
     {
 		(yyval.sym) = S;
 	}
     break;
 
   case 159:
-#line 1102 "go.y"
+#line 1105 "go.y"
     {
 		Pkg *p;
 
@@ -3616,7 +3619,7 @@
     break;
 
   case 160:
-#line 1117 "go.y"
+#line 1120 "go.y"
     {
 		(yyval.node) = oldname((yyvsp[(1) - (1)].sym));
 		if((yyval.node)->pack != N)
@@ -3625,7 +3628,7 @@
     break;
 
   case 162:
-#line 1137 "go.y"
+#line 1140 "go.y"
     {
 		yyerror("final argument in variadic function missing type");
 		(yyval.node) = nod(ODDD, typenod(typ(TINTER)), N);
@@ -3633,35 +3636,35 @@
     break;
 
   case 163:
-#line 1142 "go.y"
+#line 1145 "go.y"
     {
 		(yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 169:
-#line 1153 "go.y"
+#line 1156 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
   case 173:
-#line 1162 "go.y"
+#line 1165 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 178:
-#line 1172 "go.y"
+#line 1175 "go.y"
     {
 		(yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N);
 	}
     break;
 
   case 188:
-#line 1193 "go.y"
+#line 1196 "go.y"
     {
 		if((yyvsp[(1) - (3)].node)->op == OPACK) {
 			Sym *s;
@@ -3675,14 +3678,14 @@
     break;
 
   case 189:
-#line 1206 "go.y"
+#line 1209 "go.y"
     {
 		(yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node));
 	}
     break;
 
   case 190:
-#line 1210 "go.y"
+#line 1213 "go.y"
     {
 		// array literal of nelem
 		(yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node));
@@ -3690,7 +3693,7 @@
     break;
 
   case 191:
-#line 1215 "go.y"
+#line 1218 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->etype = Cboth;
@@ -3698,7 +3701,7 @@
     break;
 
   case 192:
-#line 1220 "go.y"
+#line 1223 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Csend;
@@ -3706,21 +3709,21 @@
     break;
 
   case 193:
-#line 1225 "go.y"
+#line 1228 "go.y"
     {
 		(yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
 	}
     break;
 
   case 196:
-#line 1233 "go.y"
+#line 1236 "go.y"
     {
 		(yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 197:
-#line 1239 "go.y"
+#line 1242 "go.y"
     {
 		(yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N);
 		(yyval.node)->etype = Crecv;
@@ -3728,7 +3731,7 @@
     break;
 
   case 198:
-#line 1246 "go.y"
+#line 1249 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3737,7 +3740,7 @@
     break;
 
   case 199:
-#line 1252 "go.y"
+#line 1255 "go.y"
     {
 		(yyval.node) = nod(OTSTRUCT, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
@@ -3745,7 +3748,7 @@
     break;
 
   case 200:
-#line 1259 "go.y"
+#line 1262 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		(yyval.node)->list = (yyvsp[(3) - (5)].list);
@@ -3754,7 +3757,7 @@
     break;
 
   case 201:
-#line 1265 "go.y"
+#line 1268 "go.y"
     {
 		(yyval.node) = nod(OTINTER, N, N);
 		fixlbrace((yyvsp[(2) - (3)].i));
@@ -3762,7 +3765,7 @@
     break;
 
   case 202:
-#line 1276 "go.y"
+#line 1279 "go.y"
     {
 		(yyval.node) = (yyvsp[(2) - (3)].node);
 		if((yyval.node) == N)
@@ -3777,7 +3780,7 @@
     break;
 
   case 203:
-#line 1290 "go.y"
+#line 1293 "go.y"
     {
 		Node *t;
 
@@ -3809,7 +3812,7 @@
     break;
 
   case 204:
-#line 1319 "go.y"
+#line 1322 "go.y"
     {
 		Node *rcvr, *t;
 
@@ -3850,7 +3853,7 @@
     break;
 
   case 205:
-#line 1359 "go.y"
+#line 1362 "go.y"
     {
 		Sym *s;
 		Type *t;
@@ -3878,7 +3881,7 @@
     break;
 
   case 206:
-#line 1384 "go.y"
+#line 1387 "go.y"
     {
 		(yyval.node) = methodname1(newname((yyvsp[(4) - (8)].sym)), (yyvsp[(2) - (8)].list)->n->right); 
 		(yyval.node)->type = functype((yyvsp[(2) - (8)].list)->n, (yyvsp[(6) - (8)].list), (yyvsp[(8) - (8)].list));
@@ -3897,7 +3900,7 @@
     break;
 
   case 207:
-#line 1402 "go.y"
+#line 1405 "go.y"
     {
 		(yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1);
 		(yyval.node) = nod(OTFUNC, N, N);
@@ -3907,14 +3910,14 @@
     break;
 
   case 208:
-#line 1410 "go.y"
+#line 1413 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 209:
-#line 1414 "go.y"
+#line 1417 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 		if((yyval.list) == nil)
@@ -3923,21 +3926,21 @@
     break;
 
   case 210:
-#line 1422 "go.y"
+#line 1425 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 211:
-#line 1426 "go.y"
+#line 1429 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node)));
 	}
     break;
 
   case 212:
-#line 1430 "go.y"
+#line 1433 "go.y"
     {
 		(yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0);
 		(yyval.list) = (yyvsp[(2) - (3)].list);
@@ -3945,14 +3948,14 @@
     break;
 
   case 213:
-#line 1437 "go.y"
+#line 1440 "go.y"
     {
 		closurehdr((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 214:
-#line 1443 "go.y"
+#line 1446 "go.y"
     {
 		(yyval.node) = closurebody((yyvsp[(3) - (4)].list));
 		fixlbrace((yyvsp[(2) - (4)].i));
@@ -3960,21 +3963,21 @@
     break;
 
   case 215:
-#line 1448 "go.y"
+#line 1451 "go.y"
     {
 		(yyval.node) = closurebody(nil);
 	}
     break;
 
   case 216:
-#line 1459 "go.y"
+#line 1462 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 217:
-#line 1463 "go.y"
+#line 1466 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list));
 		if(nsyntaxerrors == 0)
@@ -3985,56 +3988,56 @@
     break;
 
   case 219:
-#line 1474 "go.y"
+#line 1477 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 221:
-#line 1481 "go.y"
+#line 1484 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 222:
-#line 1487 "go.y"
+#line 1490 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 223:
-#line 1491 "go.y"
+#line 1494 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 225:
-#line 1498 "go.y"
+#line 1501 "go.y"
     {
 		(yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list));
 	}
     break;
 
   case 226:
-#line 1504 "go.y"
+#line 1507 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 227:
-#line 1508 "go.y"
+#line 1511 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 228:
-#line 1514 "go.y"
+#line 1517 "go.y"
     {
 		NodeList *l;
 
@@ -4060,7 +4063,7 @@
     break;
 
   case 229:
-#line 1537 "go.y"
+#line 1540 "go.y"
     {
 		(yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val);
 		(yyval.list) = list1((yyvsp[(1) - (2)].node));
@@ -4068,7 +4071,7 @@
     break;
 
   case 230:
-#line 1542 "go.y"
+#line 1545 "go.y"
     {
 		(yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val);
 		(yyval.list) = list1((yyvsp[(2) - (4)].node));
@@ -4077,7 +4080,7 @@
     break;
 
   case 231:
-#line 1548 "go.y"
+#line 1551 "go.y"
     {
 		(yyvsp[(2) - (3)].node)->right = nod(OIND, (yyvsp[(2) - (3)].node)->right, N);
 		(yyvsp[(2) - (3)].node)->val = (yyvsp[(3) - (3)].val);
@@ -4086,7 +4089,7 @@
     break;
 
   case 232:
-#line 1554 "go.y"
+#line 1557 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4096,7 +4099,7 @@
     break;
 
   case 233:
-#line 1561 "go.y"
+#line 1564 "go.y"
     {
 		(yyvsp[(3) - (5)].node)->right = nod(OIND, (yyvsp[(3) - (5)].node)->right, N);
 		(yyvsp[(3) - (5)].node)->val = (yyvsp[(5) - (5)].val);
@@ -4106,7 +4109,7 @@
     break;
 
   case 234:
-#line 1570 "go.y"
+#line 1573 "go.y"
     {
 		Node *n;
 
@@ -4118,7 +4121,7 @@
     break;
 
   case 235:
-#line 1579 "go.y"
+#line 1582 "go.y"
     {
 		Pkg *pkg;
 
@@ -4134,14 +4137,14 @@
     break;
 
   case 236:
-#line 1594 "go.y"
+#line 1597 "go.y"
     {
 		(yyval.node) = embedded((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 237:
-#line 1600 "go.y"
+#line 1603 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
 		ifacedcl((yyval.node));
@@ -4149,14 +4152,14 @@
     break;
 
   case 238:
-#line 1605 "go.y"
+#line 1608 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym)));
 	}
     break;
 
   case 239:
-#line 1609 "go.y"
+#line 1612 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym)));
 		yyerror("cannot parenthesize embedded type");
@@ -4164,7 +4167,7 @@
     break;
 
   case 240:
-#line 1616 "go.y"
+#line 1619 "go.y"
     {
 		// without func keyword
 		(yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1);
@@ -4175,7 +4178,7 @@
     break;
 
   case 242:
-#line 1630 "go.y"
+#line 1633 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4184,7 +4187,7 @@
     break;
 
   case 243:
-#line 1636 "go.y"
+#line 1639 "go.y"
     {
 		(yyval.node) = nod(ONONAME, N, N);
 		(yyval.node)->sym = (yyvsp[(1) - (2)].sym);
@@ -4193,56 +4196,56 @@
     break;
 
   case 245:
-#line 1645 "go.y"
+#line 1648 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 246:
-#line 1649 "go.y"
+#line 1652 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 247:
-#line 1654 "go.y"
+#line 1657 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 248:
-#line 1658 "go.y"
+#line 1661 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
   case 249:
-#line 1666 "go.y"
+#line 1669 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 251:
-#line 1671 "go.y"
+#line 1674 "go.y"
     {
 		(yyval.node) = liststmt((yyvsp[(1) - (1)].list));
 	}
     break;
 
   case 253:
-#line 1676 "go.y"
+#line 1679 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 259:
-#line 1687 "go.y"
+#line 1690 "go.y"
     {
 		(yyvsp[(1) - (2)].node) = nod(OLABEL, (yyvsp[(1) - (2)].node), N);
 		(yyvsp[(1) - (2)].node)->sym = dclstack;  // context, for goto restrictions
@@ -4250,7 +4253,7 @@
     break;
 
   case 260:
-#line 1692 "go.y"
+#line 1695 "go.y"
     {
 		NodeList *l;
 
@@ -4263,7 +4266,7 @@
     break;
 
   case 261:
-#line 1702 "go.y"
+#line 1705 "go.y"
     {
 		// will be converted to OFALL
 		(yyval.node) = nod(OXFALL, N, N);
@@ -4271,35 +4274,35 @@
     break;
 
   case 262:
-#line 1707 "go.y"
+#line 1710 "go.y"
     {
 		(yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 263:
-#line 1711 "go.y"
+#line 1714 "go.y"
     {
 		(yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 264:
-#line 1715 "go.y"
+#line 1718 "go.y"
     {
 		(yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 265:
-#line 1719 "go.y"
+#line 1722 "go.y"
     {
 		(yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N);
 	}
     break;
 
   case 266:
-#line 1723 "go.y"
+#line 1726 "go.y"
     {
 		(yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N);
 		(yyval.node)->sym = dclstack;  // context, for goto restrictions
@@ -4307,7 +4310,7 @@
     break;
 
   case 267:
-#line 1728 "go.y"
+#line 1731 "go.y"
     {
 		(yyval.node) = nod(ORETURN, N, N);
 		(yyval.node)->list = (yyvsp[(2) - (2)].list);
@@ -4327,7 +4330,7 @@
     break;
 
   case 268:
-#line 1747 "go.y"
+#line 1750 "go.y"
     {
 		(yyval.list) = nil;
 		if((yyvsp[(1) - (1)].node) != N)
@@ -4336,7 +4339,7 @@
     break;
 
   case 269:
-#line 1753 "go.y"
+#line 1756 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (3)].list);
 		if((yyvsp[(3) - (3)].node) != N)
@@ -4345,189 +4348,189 @@
     break;
 
   case 270:
-#line 1761 "go.y"
+#line 1764 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 271:
-#line 1765 "go.y"
+#line 1768 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 272:
-#line 1771 "go.y"
+#line 1774 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 273:
-#line 1775 "go.y"
+#line 1778 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 274:
-#line 1781 "go.y"
+#line 1784 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 275:
-#line 1785 "go.y"
+#line 1788 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 276:
-#line 1791 "go.y"
+#line 1794 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 277:
-#line 1795 "go.y"
+#line 1798 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 278:
-#line 1804 "go.y"
+#line 1807 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 279:
-#line 1808 "go.y"
+#line 1811 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 280:
-#line 1812 "go.y"
+#line 1815 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 281:
-#line 1816 "go.y"
+#line 1819 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 282:
-#line 1821 "go.y"
+#line 1824 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 283:
-#line 1825 "go.y"
+#line 1828 "go.y"
     {
 		(yyval.list) = (yyvsp[(1) - (2)].list);
 	}
     break;
 
   case 288:
-#line 1839 "go.y"
+#line 1842 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 290:
-#line 1845 "go.y"
+#line 1848 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 292:
-#line 1851 "go.y"
+#line 1854 "go.y"
     {
 		(yyval.node) = N;
 	}
     break;
 
   case 294:
-#line 1857 "go.y"
+#line 1860 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 296:
-#line 1863 "go.y"
+#line 1866 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 298:
-#line 1869 "go.y"
+#line 1872 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 300:
-#line 1875 "go.y"
+#line 1878 "go.y"
     {
 		(yyval.val).ctype = CTxxx;
 	}
     break;
 
   case 302:
-#line 1885 "go.y"
+#line 1888 "go.y"
     {
 		importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval);
 	}
     break;
 
   case 303:
-#line 1889 "go.y"
+#line 1892 "go.y"
     {
 		importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type));
 	}
     break;
 
   case 304:
-#line 1893 "go.y"
+#line 1896 "go.y"
     {
 		importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node));
 	}
     break;
 
   case 305:
-#line 1897 "go.y"
+#line 1900 "go.y"
     {
 		importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node));
 	}
     break;
 
   case 306:
-#line 1901 "go.y"
+#line 1904 "go.y"
     {
 		importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type));
 	}
     break;
 
   case 307:
-#line 1905 "go.y"
+#line 1908 "go.y"
     {
 		if((yyvsp[(2) - (4)].node) == N) {
 			dclcontext = PEXTERN;  // since we skip the funcbody below
@@ -4548,7 +4551,7 @@
     break;
 
   case 308:
-#line 1925 "go.y"
+#line 1928 "go.y"
     {
 		(yyval.sym) = (yyvsp[(1) - (1)].sym);
 		structpkg = (yyval.sym)->pkg;
@@ -4556,7 +4559,7 @@
     break;
 
   case 309:
-#line 1932 "go.y"
+#line 1935 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 		importsym((yyvsp[(1) - (1)].sym), OTYPE);
@@ -4564,14 +4567,14 @@
     break;
 
   case 315:
-#line 1952 "go.y"
+#line 1955 "go.y"
     {
 		(yyval.type) = pkgtype((yyvsp[(1) - (1)].sym));
 	}
     break;
 
   case 316:
-#line 1956 "go.y"
+#line 1959 "go.y"
     {
 		// predefined name like uint8
 		(yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg);
@@ -4584,49 +4587,49 @@
     break;
 
   case 317:
-#line 1966 "go.y"
+#line 1969 "go.y"
     {
 		(yyval.type) = aindex(N, (yyvsp[(3) - (3)].type));
 	}
     break;
 
   case 318:
-#line 1970 "go.y"
+#line 1973 "go.y"
     {
 		(yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type));
 	}
     break;
 
   case 319:
-#line 1974 "go.y"
+#line 1977 "go.y"
     {
 		(yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type));
 	}
     break;
 
   case 320:
-#line 1978 "go.y"
+#line 1981 "go.y"
     {
 		(yyval.type) = tostruct((yyvsp[(3) - (4)].list));
 	}
     break;
 
   case 321:
-#line 1982 "go.y"
+#line 1985 "go.y"
     {
 		(yyval.type) = tointerface((yyvsp[(3) - (4)].list));
 	}
     break;
 
   case 322:
-#line 1986 "go.y"
+#line 1989 "go.y"
     {
 		(yyval.type) = ptrto((yyvsp[(2) - (2)].type));
 	}
     break;
 
   case 323:
-#line 1990 "go.y"
+#line 1993 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(2) - (2)].type);
@@ -4635,7 +4638,7 @@
     break;
 
   case 324:
-#line 1996 "go.y"
+#line 1999 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (4)].type);
@@ -4644,7 +4647,7 @@
     break;
 
   case 325:
-#line 2002 "go.y"
+#line 2005 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4653,7 +4656,7 @@
     break;
 
   case 326:
-#line 2010 "go.y"
+#line 2013 "go.y"
     {
 		(yyval.type) = typ(TCHAN);
 		(yyval.type)->type = (yyvsp[(3) - (3)].type);
@@ -4662,14 +4665,14 @@
     break;
 
   case 327:
-#line 2018 "go.y"
+#line 2021 "go.y"
     {
 		(yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list));
 	}
     break;
 
   case 328:
-#line 2024 "go.y"
+#line 2027 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type)));
 		if((yyvsp[(1) - (3)].sym))
@@ -4679,7 +4682,7 @@
     break;
 
   case 329:
-#line 2031 "go.y"
+#line 2034 "go.y"
     {
 		Type *t;
 	
@@ -4696,7 +4699,7 @@
     break;
 
   case 330:
-#line 2047 "go.y"
+#line 2050 "go.y"
     {
 		Sym *s;
 
@@ -4715,49 +4718,49 @@
     break;
 
   case 331:
-#line 2065 "go.y"
+#line 2068 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, newname((yyvsp[(1) - (5)].sym)), typenod(functype(fakethis(), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list))));
 	}
     break;
 
   case 332:
-#line 2069 "go.y"
+#line 2072 "go.y"
     {
 		(yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)));
 	}
     break;
 
   case 333:
-#line 2074 "go.y"
+#line 2077 "go.y"
     {
 		(yyval.list) = nil;
 	}
     break;
 
   case 335:
-#line 2081 "go.y"
+#line 2084 "go.y"
     {
 		(yyval.list) = (yyvsp[(2) - (3)].list);
 	}
     break;
 
   case 336:
-#line 2085 "go.y"
+#line 2088 "go.y"
     {
 		(yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))));
 	}
     break;
 
   case 337:
-#line 2095 "go.y"
+#line 2098 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(1) - (1)].val));
 	}
     break;
 
   case 338:
-#line 2099 "go.y"
+#line 2102 "go.y"
     {
 		(yyval.node) = nodlit((yyvsp[(2) - (2)].val));
 		switch((yyval.node)->val.ctype){
@@ -4775,7 +4778,7 @@
     break;
 
   case 339:
-#line 2114 "go.y"
+#line 2117 "go.y"
     {
 		(yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg));
 		if((yyval.node)->op != OLITERAL)
@@ -4784,7 +4787,7 @@
     break;
 
   case 341:
-#line 2123 "go.y"
+#line 2126 "go.y"
     {
 		if((yyvsp[(2) - (5)].node)->val.ctype == CTRUNE && (yyvsp[(4) - (5)].node)->val.ctype == CTINT) {
 			(yyval.node) = (yyvsp[(2) - (5)].node);
@@ -4798,42 +4801,42 @@
     break;
 
   case 344:
-#line 2139 "go.y"
+#line 2142 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 345:
-#line 2143 "go.y"
+#line 2146 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 346:
-#line 2149 "go.y"
+#line 2152 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 347:
-#line 2153 "go.y"
+#line 2156 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
     break;
 
   case 348:
-#line 2159 "go.y"
+#line 2162 "go.y"
     {
 		(yyval.list) = list1((yyvsp[(1) - (1)].node));
 	}
     break;
 
   case 349:
-#line 2163 "go.y"
+#line 2166 "go.y"
     {
 		(yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node));
 	}
@@ -4841,7 +4844,7 @@
 
 
 /* Line 1267 of yacc.c.  */
-#line 4846 "y.tab.c"
+#line 4849 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -5055,7 +5058,7 @@
 }
 
 
-#line 2167 "go.y"
+#line 2170 "go.y"
 
 
 static void
diff --git a/test/fixedbugs/bug086.go b/test/fixedbugs/bug086.go
index fc69e0e..f03982b 100644
--- a/test/fixedbugs/bug086.go
+++ b/test/fixedbugs/bug086.go
@@ -6,12 +6,12 @@
 
 package main
 
-func f() int {	// ERROR "return|control"
+func f() int {	// GCCGO_ERROR "control"
 	if false {
 		return 0;
 	}
 	// we should not be able to return successfully w/o a return statement
-}
+} // GC_ERROR "return"
 
 func main() {
 	print(f(), "\n");
diff --git a/test/fixedbugs/issue4663.go b/test/fixedbugs/issue4663.go
index b3d6602..edaee93 100644
--- a/test/fixedbugs/issue4663.go
+++ b/test/fixedbugs/issue4663.go
@@ -11,4 +11,5 @@
 
 func a(b int) int64 {
   b // ERROR "not used"
+  return 0
 }
diff --git a/test/return.go b/test/return.go
new file mode 100644
index 0000000..aebbf78
--- /dev/null
+++ b/test/return.go
@@ -0,0 +1,1453 @@
+// errorcheck
+
+// Copyright 2013 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test compiler diagnosis of function missing return statements.
+// See issue 65 and golang.org/s/go11return.
+
+package p
+
+type T int
+
+var x interface{}
+var c chan int
+
+func external() int // ok
+
+func _() int {
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+	print(1)
+	return 2
+}
+
+// goto is okay
+func _() int {
+L:
+	print(1)
+	goto L
+}
+
+// panic is okay
+func _() int {
+	print(1)
+	panic(2)
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	print(1)
+	panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+	print(1)
+	return 2
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	goto L
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	panic(2)
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+	print(1)
+	return 2
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	goto L
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	panic(2)
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		print(1)
+		return 2
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		print(1)
+		goto L
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	{
+		panic(2)
+	}
+	{}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	if x == nil {
+		panic(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+	print(1)
+	for {}
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+}
+
+func _() int {
+	for {
+		L:
+		for {
+			break L
+		}
+	}
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+	print(1)
+	for { break }
+} // ERROR "missing return"
+
+func _() int {
+	for {
+		for {
+		}
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+	print(1)
+	for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		L:
+		for {
+			break L
+		}
+	}	
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	for true {}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		L:
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+	print(1)
+	select{}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		for{}
+	}
+}
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+}
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select{}
+	}
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L
+	case c <- 1:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+	print(1)
+	select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		for{ break L }
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	select {
+	case <-c:
+		print(1)
+		panic("abc")
+	default:
+		select{}
+		break
+	}
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	print(1)
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x {
+	default:
+		return 4
+		break
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	print(1)
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+	switch x.(type) {
+	default:
+		return 4
+		break
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	print(1)
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// again, but without the leading print(1).
+// testing that everything works when the terminating statement is first.
+
+func _() int {
+} // ERROR "missing return"
+
+// return is okay
+func _() int {
+	return 2
+}
+
+// goto is okay
+func _() int {
+L:
+	goto L
+}
+
+// panic is okay
+func _() int {
+	panic(2)
+}
+
+// but only builtin panic
+func _() int {
+	var panic = func(int) {}
+	panic(2)
+} // ERROR "missing return"
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		return 2
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+L:
+	{
+		goto L
+	}
+}
+
+// block ending in terminating statement is okay
+func _() int {
+	{
+		panic(2)
+	}
+}
+
+// adding more code - even though it is dead - now requires a return
+
+func _() int {
+	return 2
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	goto L
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	panic(2)
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+		print(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	print(3)
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+	}
+	print(3)
+} // ERROR "missing return"
+
+// even an empty dead block triggers the message, because it
+// becomes the final statement.
+
+func _() int {
+	return 2
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	goto L
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	panic(2)
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+		{}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		return 2
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	{
+		goto L
+	}
+	{}
+} // ERROR "missing return"
+
+func _() int {
+	{
+		panic(2)
+	}
+	{}
+} // ERROR "missing return"
+
+// if-else chain with final else and all terminating is okay
+
+func _() int {
+	if x == nil {
+		panic(2)
+	} else {
+		panic(3)
+	}
+}
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else {
+		goto L
+	}
+}
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 2 {
+		panic(3)
+	} else {
+		goto L
+	}
+}
+
+// if-else chain missing final else is not okay, even if the
+// conditions cover every possible case.
+
+func _() int {
+	if x == nil {
+		panic(2)
+	} else if x != nil {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	if x == nil {
+		panic(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	if x == nil {
+		panic(2)
+	} else if x == 1 {
+		return 0
+	} else if x != 1 {
+		panic(3)
+	}
+} // ERROR "missing return"
+
+
+// for { loops that never break are okay.
+
+func _() int {
+	for {}
+}
+
+func _() int {
+	for {
+		for {
+			break
+		}
+	}
+}
+
+func _() int {
+	for {
+		L:
+		for {
+			break L
+		}
+	}
+}
+
+// for { loops that break are not okay.
+
+func _() int {
+	for { break }
+} // ERROR "missing return"
+
+func _() int {
+	for {
+		for {
+		}
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	for {
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// if there's a condition - even "true" - the loops are no longer syntactically terminating
+
+func _() int {
+	for x == nil {}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for x == nil {
+		L:
+		for {
+			break L
+		}
+	}	
+} // ERROR "missing return"
+
+func _() int {
+	for true {}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		for {
+			break
+		}
+	}
+} // ERROR "missing return"
+
+func _() int {
+	for true {
+		L:
+		for {
+			break L
+		}
+	}
+} // ERROR "missing return"
+
+// select in which all cases terminate and none break are okay.
+
+func _() int {
+	select{}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		for{}
+	}
+}
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		goto L
+	}
+}
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		select{}
+	}
+}
+
+// if any cases don't terminate, the select isn't okay anymore
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		goto L
+	case c <- 1:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	default:
+		print(2)
+	}
+} // ERROR "missing return"
+
+
+// if any breaks refer to the select, the select isn't okay anymore, even if they're dead
+
+func _() int {
+	select{ default: break }
+} // ERROR "missing return"
+
+func _() int {
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+		break
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		for{ break L }
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	select {
+	case <-c:
+		print(2)
+		panic("abc")
+	case c <- 1:
+		print(2)
+		break L
+	}
+} // ERROR "missing return"
+
+func _() int {
+	select {
+	case <-c:
+		panic("abc")
+	default:
+		select{}
+		break
+	}
+} // ERROR "missing return"
+
+// switch with default in which all cases terminate is okay
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	switch x {
+	default:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 2:
+		return 4
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		fallthrough
+	case 2:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+	switch x {
+	case 1:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x {
+	default:
+		return 4
+		break
+	case 1:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	switch x {
+	case 1:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+// type switch with default in which all cases terminate is okay
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	default:
+		return 4
+	}
+}
+
+func _() int {
+	switch x.(type) {
+	default:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+}
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	default:
+		return 4
+	}
+}
+
+// if no default or some case doesn't terminate, switch is no longer okay
+
+func _() int {
+	switch {
+	}
+} // ERROR "missing return"
+
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case float64:
+		return 4
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		fallthrough
+	case float64:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+// if any breaks refer to the switch, switch is no longer okay
+
+func _() int {
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		panic(3)
+		break L
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+func _() int {
+	switch x.(type) {
+	default:
+		return 4
+		break
+	case int:
+		print(2)
+		panic(3)
+	}
+} // ERROR "missing return"
+
+func _() int {
+L:
+	switch x.(type) {
+	case int:
+		print(2)
+		for {
+			break L
+		}
+	default:
+		return 4
+	}
+} // ERROR "missing return"
+
+/**/