From: Russ Cox Date: Mon, 4 Mar 2013 22:02:04 +0000 (-0500) Subject: cmd/gc: implement new return requirements X-Git-Tag: go1.1rc2~693 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=ecab408c4223be3f49d9df52f2900a35bc68f444;p=gostls13.git 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 f86c152f2c..7e5e1b7356 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -268,6 +268,7 @@ struct Node 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 @@ Node* typecheck(Node **np, int top); 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 794961e8e7..a12da56712 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -536,7 +536,10 @@ compound_stmt: } 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 68ae6864d0..118a0d7a0c 100644 --- a/src/cmd/gc/lex.c +++ b/src/cmd/gc/lex.c @@ -376,6 +376,7 @@ main(int argc, char *argv[]) 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 fbab85d033..47e555f945 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -3144,3 +3144,148 @@ checkmake(Type *t, char *arg, Node *n) } 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 de2105ed39..831917f149 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -29,40 +29,6 @@ static void walkdiv(Node**, NodeList**); 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 @@ walk(Node *fn) 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 75175455ea..dee793998a 100644 --- a/src/cmd/gc/y.tab.c +++ b/src/cmd/gc/y.tab.c @@ -662,35 +662,35 @@ static const yytype_uint16 yyrline[] = 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 @@ yyreduce: 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 @@ yyreduce: break; case 63: -#line 555 "go.y" +#line 558 "go.y" { int last; @@ -2908,28 +2911,28 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 71: -#line 622 "go.y" +#line 625 "go.y" { // normal test (yyval.node) = nod(OFOR, N, N); @@ -2979,7 +2982,7 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 76: -#line 649 "go.y" +#line 652 "go.y" { // test (yyval.node) = nod(OIF, N, N); @@ -3011,7 +3014,7 @@ yyreduce: break; case 77: -#line 655 "go.y" +#line 658 "go.y" { // init ; test (yyval.node) = nod(OIF, N, N); @@ -3022,14 +3025,14 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 146: -#line 1026 "go.y" +#line 1029 "go.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -3545,21 +3548,21 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 203: -#line 1290 "go.y" +#line 1293 "go.y" { Node *t; @@ -3809,7 +3812,7 @@ yyreduce: break; case 204: -#line 1319 "go.y" +#line 1322 "go.y" { Node *rcvr, *t; @@ -3850,7 +3853,7 @@ yyreduce: break; case 205: -#line 1359 "go.y" +#line 1362 "go.y" { Sym *s; Type *t; @@ -3878,7 +3881,7 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 234: -#line 1570 "go.y" +#line 1573 "go.y" { Node *n; @@ -4118,7 +4121,7 @@ yyreduce: break; case 235: -#line 1579 "go.y" +#line 1582 "go.y" { Pkg *pkg; @@ -4134,14 +4137,14 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 260: -#line 1692 "go.y" +#line 1695 "go.y" { NodeList *l; @@ -4263,7 +4266,7 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 268: -#line 1747 "go.y" +#line 1750 "go.y" { (yyval.list) = nil; if((yyvsp[(1) - (1)].node) != N) @@ -4336,7 +4339,7 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: break; case 329: -#line 2031 "go.y" +#line 2034 "go.y" { Type *t; @@ -4696,7 +4699,7 @@ yyreduce: break; case 330: -#line 2047 "go.y" +#line 2050 "go.y" { Sym *s; @@ -4715,49 +4718,49 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: 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 @@ yyreduce: /* 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 @@ yyreturn: } -#line 2167 "go.y" +#line 2170 "go.y" static void diff --git a/test/fixedbugs/bug086.go b/test/fixedbugs/bug086.go index fc69e0e3fc..f03982b303 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 b3d660287a..edaee93c5b 100644 --- a/test/fixedbugs/issue4663.go +++ b/test/fixedbugs/issue4663.go @@ -11,4 +11,5 @@ package main 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 0000000000..aebbf78b74 --- /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" + +/**/