diff options
Diffstat (limited to 'src/cmd/gc')
-rw-r--r-- | src/cmd/gc/align.c | 7 | ||||
-rw-r--r-- | src/cmd/gc/builtin.c | 7 | ||||
-rw-r--r-- | src/cmd/gc/closure.c | 194 | ||||
-rw-r--r-- | src/cmd/gc/const.c | 36 | ||||
-rw-r--r-- | src/cmd/gc/cplx.c | 8 | ||||
-rw-r--r-- | src/cmd/gc/dcl.c | 56 | ||||
-rw-r--r-- | src/cmd/gc/esc.c | 13 | ||||
-rw-r--r-- | src/cmd/gc/fmt.c | 11 | ||||
-rw-r--r-- | src/cmd/gc/gen.c | 7 | ||||
-rw-r--r-- | src/cmd/gc/go.h | 26 | ||||
-rw-r--r-- | src/cmd/gc/go.y | 8 | ||||
-rw-r--r-- | src/cmd/gc/inl.c | 32 | ||||
-rw-r--r-- | src/cmd/gc/lex.c | 11 | ||||
-rwxr-xr-x | src/cmd/gc/mkbuiltin | 1 | ||||
-rw-r--r-- | src/cmd/gc/obj.c | 14 | ||||
-rw-r--r-- | src/cmd/gc/pgen.c | 13 | ||||
-rw-r--r-- | src/cmd/gc/racewalk.c | 162 | ||||
-rw-r--r-- | src/cmd/gc/range.c | 6 | ||||
-rw-r--r-- | src/cmd/gc/reflect.c | 46 | ||||
-rw-r--r-- | src/cmd/gc/runtime.go | 6 | ||||
-rw-r--r-- | src/cmd/gc/sinit.c | 8 | ||||
-rw-r--r-- | src/cmd/gc/subr.c | 54 | ||||
-rw-r--r-- | src/cmd/gc/swt.c | 6 | ||||
-rw-r--r-- | src/cmd/gc/typecheck.c | 204 | ||||
-rw-r--r-- | src/cmd/gc/unsafe.c | 42 | ||||
-rw-r--r-- | src/cmd/gc/walk.c | 185 | ||||
-rw-r--r-- | src/cmd/gc/y.tab.c | 594 |
27 files changed, 1216 insertions, 541 deletions
diff --git a/src/cmd/gc/align.c b/src/cmd/gc/align.c index be9f552f6..80c65387b 100644 --- a/src/cmd/gc/align.c +++ b/src/cmd/gc/align.c @@ -46,7 +46,8 @@ static vlong widstruct(Type *errtype, Type *t, vlong o, int flag) { Type *f; - int32 w, maxalign; + int64 w; + int32 maxalign; maxalign = flag; if(maxalign < 1) @@ -643,7 +644,7 @@ argsize(Type *t) { Iter save; Type *fp; - int w, x; + int64 w, x; w = 0; @@ -664,5 +665,7 @@ argsize(Type *t) } w = (w+widthptr-1) & ~(widthptr-1); + if((int)w != w) + fatal("argsize too big"); return w; } diff --git a/src/cmd/gc/builtin.c b/src/cmd/gc/builtin.c index 7de448d1e..9053dfe10 100644 --- a/src/cmd/gc/builtin.c +++ b/src/cmd/gc/builtin.c @@ -1,3 +1,4 @@ +// AUTO-GENERATED by mkbuiltin; DO NOT EDIT char *runtimeimport = "package runtime\n" "import runtime \"runtime\"\n" @@ -63,7 +64,13 @@ char *runtimeimport = "func @\"\".equal (@\"\".typ·2 *byte, @\"\".x1·3 any, @\"\".x2·4 any) (@\"\".ret·1 bool)\n" "func @\"\".makemap (@\"\".mapType·2 *byte, @\"\".hint·3 int64) (@\"\".hmap·1 map[any]any)\n" "func @\"\".mapaccess1 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 any)\n" + "func @\"\".mapaccess1_fast32 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n" + "func @\"\".mapaccess1_fast64 (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n" + "func @\"\".mapaccess1_faststr (@\"\".mapType·2 *byte, @\"\".hmap·3 map[any]any, @\"\".key·4 any) (@\"\".val·1 *any)\n" "func @\"\".mapaccess2 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 any, @\"\".pres·2 bool)\n" + "func @\"\".mapaccess2_fast32 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n" + "func @\"\".mapaccess2_fast64 (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n" + "func @\"\".mapaccess2_faststr (@\"\".mapType·3 *byte, @\"\".hmap·4 map[any]any, @\"\".key·5 any) (@\"\".val·1 *any, @\"\".pres·2 bool)\n" "func @\"\".mapassign1 (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any, @\"\".val·4 any)\n" "func @\"\".mapiterinit (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".hiter·3 *any)\n" "func @\"\".mapdelete (@\"\".mapType·1 *byte, @\"\".hmap·2 map[any]any, @\"\".key·3 any)\n" diff --git a/src/cmd/gc/closure.c b/src/cmd/gc/closure.c index 4e029ef83..d81c5281d 100644 --- a/src/cmd/gc/closure.c +++ b/src/cmd/gc/closure.c @@ -60,6 +60,7 @@ closurebody(NodeList *body) func = curfn; func->nbody = body; + func->endlineno = lineno; funcbody(func); // closure-specific variables are hanging off the @@ -75,7 +76,7 @@ closurebody(NodeList *body) return func; } -static Node* makeclosure(Node *func, int nowrap); +static Node* makeclosure(Node *func); void typecheckclosure(Node *func, int top) @@ -124,17 +125,17 @@ typecheckclosure(Node *func, int top) } // Create top-level function - xtop = list(xtop, makeclosure(func, func->cvars==nil || (top&Ecall))); + xtop = list(xtop, makeclosure(func)); } static Node* -makeclosure(Node *func, int nowrap) +makeclosure(Node *func) { Node *xtype, *v, *addr, *xfunc, *cv; NodeList *l, *body; static int closgen; char *p; - int offset; + vlong offset; /* * wrap body in external function @@ -154,6 +155,7 @@ makeclosure(Node *func, int nowrap) declare(xfunc->nname, PFUNC); xfunc->nname->funcdepth = func->funcdepth; xfunc->funcdepth = func->funcdepth; + xfunc->endlineno = func->endlineno; // declare variables holding addresses taken from closure // and initialize in entry prologue. @@ -255,26 +257,174 @@ walkclosure(Node *func, NodeList **init) return clos; } -// Special case for closures that get called in place. -// Optimize runtime.closure(X, __func__xxxx_, .... ) away -// to __func__xxxx_(Y ....). -// On entry, expect n->op == OCALL, n->left->op == OCLOSURE. +static Node *makepartialcall(Node*, Type*, Node*); + void -walkcallclosure(Node *n, NodeList **init) +typecheckpartialcall(Node *fn, Node *sym) +{ + switch(fn->op) { + case ODOTINTER: + case ODOTMETH: + break; + default: + fatal("invalid typecheckpartialcall"); + } + + // Create top-level function. + fn->nname = makepartialcall(fn, fn->type, sym); + fn->right = sym; + fn->op = OCALLPART; + fn->type = fn->nname->type; +} + +static Node* +makepartialcall(Node *fn, Type *t0, Node *meth) +{ + Node *ptr, *n, *fld, *call, *xtype, *xfunc, *cv; + Type *rcvrtype, *basetype, *t; + NodeList *body, *l, *callargs, *retargs; + char *p; + Sym *sym; + int i, ddd; + + // TODO: names are not right + rcvrtype = fn->left->type; + if(exportname(meth->sym->name)) + p = smprint("%-hT.%s·fm", rcvrtype, meth->sym->name); + else + p = smprint("%-hT.(%-S)·fm", rcvrtype, meth->sym); + basetype = rcvrtype; + if(isptr[rcvrtype->etype]) + basetype = basetype->type; + if(basetype->sym == S) + fatal("missing base type for %T", rcvrtype); + + sym = pkglookup(p, basetype->sym->pkg); + free(p); + if(sym->flags & SymUniq) + return sym->def; + sym->flags |= SymUniq; + + xtype = nod(OTFUNC, N, N); + i = 0; + l = nil; + callargs = nil; + ddd = 0; + xfunc = nod(ODCLFUNC, N, N); + for(t = getinargx(t0)->type; t; t = t->down) { + snprint(namebuf, sizeof namebuf, "a%d", i++); + n = newname(lookup(namebuf)); + n->class = PPARAM; + xfunc->dcl = list(xfunc->dcl, n); + callargs = list(callargs, n); + fld = nod(ODCLFIELD, n, typenod(t->type)); + if(t->isddd) { + fld->isddd = 1; + ddd = 1; + } + l = list(l, fld); + } + xtype->list = l; + i = 0; + l = nil; + retargs = nil; + for(t = getoutargx(t0)->type; t; t = t->down) { + snprint(namebuf, sizeof namebuf, "r%d", i++); + n = newname(lookup(namebuf)); + n->class = PPARAMOUT; + xfunc->dcl = list(xfunc->dcl, n); + retargs = list(retargs, n); + l = list(l, nod(ODCLFIELD, n, typenod(t->type))); + } + xtype->rlist = l; + + xfunc->dupok = 1; + xfunc->nname = newname(sym); + xfunc->nname->sym->flags |= SymExported; // disable export + xfunc->nname->ntype = xtype; + xfunc->nname->defn = xfunc; + declare(xfunc->nname, PFUNC); + + // Declare and initialize variable holding receiver. + body = nil; + cv = nod(OCLOSUREVAR, N, N); + cv->xoffset = widthptr; + cv->type = rcvrtype; + ptr = nod(ONAME, N, N); + ptr->sym = lookup("rcvr"); + ptr->class = PAUTO; + ptr->addable = 1; + ptr->ullman = 1; + ptr->used = 1; + ptr->curfn = xfunc; + xfunc->dcl = list(xfunc->dcl, ptr); + if(isptr[rcvrtype->etype] || isinter(rcvrtype)) { + ptr->ntype = typenod(rcvrtype); + body = list(body, nod(OAS, ptr, cv)); + } else { + ptr->ntype = typenod(ptrto(rcvrtype)); + body = list(body, nod(OAS, ptr, nod(OADDR, cv, N))); + } + + call = nod(OCALL, nod(OXDOT, ptr, meth), N); + call->list = callargs; + call->isddd = ddd; + if(t0->outtuple == 0) { + body = list(body, call); + } else { + n = nod(OAS2, N, N); + n->list = retargs; + n->rlist = list1(call); + body = list(body, n); + n = nod(ORETURN, N, N); + body = list(body, n); + } + + xfunc->nbody = body; + + typecheck(&xfunc, Etop); + sym->def = xfunc; + xtop = list(xtop, xfunc); + + return xfunc; +} + +Node* +walkpartialcall(Node *n, NodeList **init) { - USED(init); - if (n->op != OCALLFUNC || n->left->op != OCLOSURE) { - dump("walkcallclosure", n); - fatal("abuse of walkcallclosure"); + Node *clos, *typ; + + // Create closure in the form of a composite literal. + // For x.M with receiver (x) type T, the generated code looks like: + // + // clos = &struct{F uintptr; R T}{M.T·f, x} + // + // Like walkclosure above. + + if(isinter(n->left->type)) { + n->left = cheapexpr(n->left, init); + checknotnil(n->left, init); } - // New arg list for n. First the closure-args - // and then the original parameter list. - n->list = concat(n->left->enter, n->list); - n->left = n->left->closure->nname; - dowidth(n->left->type); - n->type = getoutargx(n->left->type); - // for a single valued function, pull the field type out of the struct - if (n->type && n->type->type && !n->type->type->down) - n->type = n->type->type->type; + typ = nod(OTSTRUCT, N, N); + typ->list = list1(nod(ODCLFIELD, newname(lookup("F")), typenod(types[TUINTPTR]))); + typ->list = list(typ->list, nod(ODCLFIELD, newname(lookup("R")), typenod(n->left->type))); + + clos = nod(OCOMPLIT, N, nod(OIND, typ, N)); + clos->esc = n->esc; + clos->right->implicit = 1; + clos->list = list1(nod(OCFUNC, n->nname->nname, N)); + clos->list = list(clos->list, n->left); + + // Force type conversion from *struct to the func type. + clos = nod(OCONVNOP, clos, N); + clos->type = n->type; + + typecheck(&clos, Erv); + // typecheck will insert a PTRLIT node under CONVNOP, + // tag it with escape analysis result. + clos->left->esc = n->esc; + walkexpr(&clos, init); + + return clos; } diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c index 4f1ff6778..e9d99df18 100644 --- a/src/cmd/gc/const.c +++ b/src/cmd/gc/const.c @@ -119,6 +119,27 @@ convlit1(Node **np, Type *t, int explicit) } n->type = t; return; + case OCOMPLEX: + if(n->type->etype == TIDEAL) { + switch(t->etype) { + default: + // If trying to convert to non-complex type, + // leave as complex128 and let typechecker complain. + t = types[TCOMPLEX128]; + //fallthrough + case TCOMPLEX128: + n->type = t; + convlit(&n->left, types[TFLOAT64]); + convlit(&n->right, types[TFLOAT64]); + break; + case TCOMPLEX64: + n->type = t; + convlit(&n->left, types[TFLOAT32]); + convlit(&n->right, types[TFLOAT32]); + break; + } + } + return; } // avoided repeated calculations, errors @@ -1068,6 +1089,11 @@ idealkind(Node *n) return k1; else return k2; + case OREAL: + case OIMAG: + return CTFLT; + case OCOMPLEX: + return CTCPLX; case OADDSTR: return CTSTR; case OANDAND: @@ -1110,7 +1136,6 @@ defaultlit(Node **np, Type *t) lno = setlineno(n); ctype = idealkind(n); - t1 = T; switch(ctype) { default: if(t != T) { @@ -1185,6 +1210,7 @@ void defaultlit2(Node **lp, Node **rp, int force) { Node *l, *r; + int lkind, rkind; l = *lp; r = *rp; @@ -1204,18 +1230,20 @@ defaultlit2(Node **lp, Node **rp, int force) convlit(lp, types[TBOOL]); convlit(rp, types[TBOOL]); } - if(isconst(l, CTCPLX) || isconst(r, CTCPLX)) { + lkind = idealkind(l); + rkind = idealkind(r); + if(lkind == CTCPLX || rkind == CTCPLX) { convlit(lp, types[TCOMPLEX128]); convlit(rp, types[TCOMPLEX128]); return; } - if(isconst(l, CTFLT) || isconst(r, CTFLT)) { + if(lkind == CTFLT || rkind == CTFLT) { convlit(lp, types[TFLOAT64]); convlit(rp, types[TFLOAT64]); return; } - if(isconst(l, CTRUNE) || isconst(r, CTRUNE)) { + if(lkind == CTRUNE || rkind == CTRUNE) { convlit(lp, runetype); convlit(rp, runetype); return; diff --git a/src/cmd/gc/cplx.c b/src/cmd/gc/cplx.c index e0127fc59..c9bab7a76 100644 --- a/src/cmd/gc/cplx.c +++ b/src/cmd/gc/cplx.c @@ -36,7 +36,7 @@ void complexmove(Node *f, Node *t) { int ft, tt; - Node n1, n2, n3, n4; + Node n1, n2, n3, n4, tmp; if(debug['g']) { dump("\ncomplexmove-f", f); @@ -62,9 +62,9 @@ complexmove(Node *f, Node *t) // make f addable. // also use temporary if possible stack overlap. if(!f->addable || overlap(f, t)) { - tempname(&n1, f->type); - complexmove(f, &n1); - f = &n1; + tempname(&tmp, f->type); + complexmove(f, &tmp); + f = &tmp; } subnode(&n1, &n2, f); diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index aa2489d9a..d3759efde 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -225,8 +225,12 @@ declare(Node *n, int ctxt) if(ctxt == PAUTO) n->xoffset = 0; - if(s->block == block) - redeclare(s, "in this block"); + if(s->block == block) { + // functype will print errors about duplicate function arguments. + // Don't repeat the error here. + if(ctxt != PPARAM && ctxt != PPARAMOUT) + redeclare(s, "in this block"); + } s->block = block; s->lastlineno = parserline(); @@ -824,22 +828,24 @@ structfield(Node *n) return f; } +static uint32 uniqgen; + static void checkdupfields(Type *t, char* what) { - Type* t1; int lno; lno = lineno; - for( ; t; t=t->down) - if(t->sym && t->nname && !isblank(t->nname)) - for(t1=t->down; t1; t1=t1->down) - if(t1->sym == t->sym) { - lineno = t->nname->lineno; - yyerror("duplicate %s %s", what, t->sym->name); - break; - } + for( ; t; t=t->down) { + if(t->sym && t->nname && !isblank(t->nname)) { + if(t->sym->uniqgen == uniqgen) { + lineno = t->nname->lineno; + yyerror("duplicate %s %s", what, t->sym->name); + } else + t->sym->uniqgen = uniqgen; + } + } lineno = lno; } @@ -865,6 +871,7 @@ tostruct(NodeList *l) if(f->broke) t->broke = 1; + uniqgen++; checkdupfields(t->type, "field"); if (!t->broke) @@ -897,7 +904,6 @@ tofunargs(NodeList *l) if(f->broke) t->broke = 1; - checkdupfields(t->type, "argument"); return t; } @@ -1004,6 +1010,7 @@ tointerface(NodeList *l) if(f->broke) t->broke = 1; + uniqgen++; checkdupfields(t->type, "method"); t = sortinter(t); checkwidth(t); @@ -1187,6 +1194,11 @@ functype(Node *this, NodeList *in, NodeList *out) t->type->down = tofunargs(out); t->type->down->down = tofunargs(in); + uniqgen++; + checkdupfields(t->type->type, "argument"); + checkdupfields(t->type->down->type, "argument"); + checkdupfields(t->type->down->down->type, "argument"); + if (t->type->broke || t->type->down->broke || t->type->down->down->broke) t->broke = 1; @@ -1327,6 +1339,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface) f = methtype(pa, 1); if(f == T) { t = pa; + if(t == T) // rely on typecheck having complained before + return; if(t != T) { if(isptr[t->etype]) { if(t->sym != S) { @@ -1335,10 +1349,8 @@ addmethod(Sym *sf, Type *t, int local, int nointerface) } t = t->type; } - } - if(t->broke) // rely on typecheck having complained before - return; - if(t != T) { + if(t->broke) // rely on typecheck having complained before + return; if(t->sym == S) { yyerror("invalid receiver type %T (%T is an unnamed type)", pa, t); return; @@ -1368,6 +1380,12 @@ addmethod(Sym *sf, Type *t, int local, int nointerface) } } + if(local && !pa->local) { + // defining method on non-local type. + yyerror("cannot define new methods on non-local type %T", pa); + return; + } + n = nod(ODCLFIELD, newname(sf), N); n->type = t; @@ -1383,12 +1401,6 @@ addmethod(Sym *sf, Type *t, int local, int nointerface) return; } - if(local && !pa->local) { - // defining method on non-local type. - yyerror("cannot define new methods on non-local type %T", pa); - return; - } - f = structfield(n); f->nointerface = nointerface; diff --git a/src/cmd/gc/esc.c b/src/cmd/gc/esc.c index 46c06d10e..df273e392 100644 --- a/src/cmd/gc/esc.c +++ b/src/cmd/gc/esc.c @@ -596,6 +596,14 @@ esc(EscState *e, Node *n) // Contents make it to memory, lose track. escassign(e, &e->theSink, n->left); break; + + case OCALLPART: + n->esc = EscNone; // until proven otherwise + e->noesc = list(e->noesc, n); + n->escloopdepth = e->loopdepth; + // Contents make it to memory, lose track. + escassign(e, &e->theSink, n->left); + break; case OMAPLIT: n->esc = EscNone; // until proven otherwise @@ -667,6 +675,7 @@ escassign(EscState *e, Node *dst, Node *src) case OCONVNOP: case OMAPLIT: case OSTRUCTLIT: + case OCALLPART: break; case ONAME: @@ -713,6 +722,7 @@ escassign(EscState *e, Node *dst, Node *src) case OMAKESLICE: case ONEW: case OCLOSURE: + case OCALLPART: escflows(e, dst, src); break; @@ -1033,7 +1043,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src) switch(src->op) { case ONAME: - if(src->class == PPARAM && leaks && src->esc != EscHeap) { + if(src->class == PPARAM && (leaks || dst->escloopdepth < 0) && src->esc != EscHeap) { src->esc = EscScope; if(debug['m']) warnl(src->lineno, "leaking param: %hN", src); @@ -1073,6 +1083,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src) case OMAPLIT: case ONEW: case OCLOSURE: + case OCALLPART: if(leaks) { src->esc = EscHeap; if(debug['m']) diff --git a/src/cmd/gc/fmt.c b/src/cmd/gc/fmt.c index ab81e6c88..35f01a5c2 100644 --- a/src/cmd/gc/fmt.c +++ b/src/cmd/gc/fmt.c @@ -168,7 +168,7 @@ Lconv(Fmt *fp) lno = a[i].incl->line - 1; // now print out start of this file } if(n == 0) - fmtprint(fp, "<epoch>"); + fmtprint(fp, "<unknown line number>"); return 0; } @@ -443,6 +443,9 @@ Zconv(Fmt *fp) fmtrune(fp, '\\'); fmtrune(fp, r); break; + case 0xFEFF: // BOM, basically disallowed in source code + fmtstrcpy(fp, "\\uFEFF"); + break; } } return 0; @@ -630,7 +633,7 @@ typefmt(Fmt *fp, Type *t) case TARRAY: if(t->bound >= 0) - return fmtprint(fp, "[%d]%T", (int)t->bound, t->type); + return fmtprint(fp, "[%lld]%T", t->bound, t->type); if(t->bound == -100) return fmtprint(fp, "[...]%T", t->type); return fmtprint(fp, "[]%T", t->type); @@ -1022,6 +1025,7 @@ static int opprec[] = { [ODOTTYPE] = 8, [ODOT] = 8, [OXDOT] = 8, + [OCALLPART] = 8, [OPLUS] = 7, [ONOT] = 7, @@ -1269,9 +1273,10 @@ exprfmt(Fmt *f, Node *n, int prec) case ODOTPTR: case ODOTINTER: case ODOTMETH: + case OCALLPART: exprfmt(f, n->left, nprec); if(n->right == N || n->right->sym == S) - fmtstrcpy(f, ".<nil>"); + return fmtstrcpy(f, ".<nil>"); return fmtprint(f, ".%hhS", n->right->sym); case ODOTTYPE: diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c index 5f03d9476..955ec2c5b 100644 --- a/src/cmd/gc/gen.c +++ b/src/cmd/gc/gen.c @@ -491,6 +491,9 @@ gen(Node *n) case ORETURN: cgen_ret(n); break; + + case OCHECKNOTNIL: + checkref(n->left, 1); } ret: @@ -807,7 +810,7 @@ cgen_slice(Node *n, Node *res) if(n->op == OSLICEARR) { if(!isptr[n->left->type->etype]) fatal("slicearr is supposed to work on pointer: %+N\n", n); - checkref(n->left); + checkref(n->left, 0); } if(isnil(n->left)) { @@ -833,7 +836,7 @@ cgen_slice(Node *n, Node *res) * <0 is pointer to next field (+1) */ int -dotoffset(Node *n, int *oary, Node **nn) +dotoffset(Node *n, int64 *oary, Node **nn) { int i; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index f86c152f2..48bcf0233 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -155,10 +155,10 @@ struct Type Type* orig; // original type (type literal or predefined type) int lineno; - // TFUNCT - uchar thistuple; - uchar outtuple; - uchar intuple; + // TFUNC + int thistuple; + int outtuple; + int intuple; uchar outnamed; Type* method; @@ -252,9 +252,7 @@ struct Node uchar embedded; // ODCLFIELD embedded type uchar colas; // OAS resulting from := uchar diag; // already printed error about this - uchar esc; // EscXXX uchar noescape; // func arguments do not escape - uchar funcdepth; uchar builtin; // built-in name, like len or close uchar walkdef; uchar typecheck; @@ -268,6 +266,9 @@ 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 + uint esc; // EscXXX + int funcdepth; // most nodes Type* type; @@ -368,6 +369,7 @@ struct Sym uchar sym; // huffman encoding in object file Sym* link; int32 npkg; // number of imported packages with this name + uint32 uniqgen; // saved and restored by dcopy Pkg* pkg; @@ -392,6 +394,7 @@ struct Pkg uchar imported; // export data of this package was parsed char exported; // import line written in export data char direct; // imported directly + char safe; // whether the package is marked as safe }; typedef struct Iter Iter; @@ -450,6 +453,7 @@ enum OCALLFUNC, // f() OCALLMETH, // t.Method() OCALLINTER, // err.Error() + OCALLPART, // t.Method (without ()) OCAP, // cap OCLOSE, // close OCLOSURE, // f = func() { etc } @@ -562,6 +566,7 @@ enum OITAB, // itable word of an interface value. OCLOSUREVAR, // variable reference at beginning of closure function OCFUNC, // reference to c function pointer (not go func value) + OCHECKNOTNIL, // emit code to ensure pointer/interface not nil // arch-specific registers OREGISTER, // a register, such as AX. @@ -987,7 +992,8 @@ Node* closurebody(NodeList *body); void closurehdr(Node *ntype); void typecheckclosure(Node *func, int top); Node* walkclosure(Node *func, NodeList **init); -void walkcallclosure(Node *n, NodeList **init); +void typecheckpartialcall(Node*, Node*); +Node* walkpartialcall(Node*, NodeList**); /* * const.c @@ -1097,7 +1103,7 @@ void cgen_eface(Node* n, Node* res); void cgen_slice(Node* n, Node* res); void clearlabels(void); void checklabels(void); -int dotoffset(Node *n, int *oary, Node **nn); +int dotoffset(Node *n, int64 *oary, Node **nn); void gen(Node *n); void genlist(NodeList *l); Node* sysfunc(char *name); @@ -1363,6 +1369,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); /* @@ -1416,7 +1423,8 @@ EXTERN Node* nodfp; int anyregalloc(void); void betypeinit(void); void bgen(Node *n, int true, int likely, Prog *to); -void checkref(Node*); +void checkref(Node *n, int force); +void checknotnil(Node*, NodeList**); void cgen(Node*, Node*); void cgen_asop(Node *n); void cgen_call(Node *n, int proc); diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 794961e8e..29cd37008 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -251,7 +251,8 @@ import_package: } else if(strcmp(importpkg->name, $2->name) != 0) yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, $2->name, importpkg->path); importpkg->direct = 1; - + importpkg->safe = curio.importsafe; + if(safemode && !curio.importsafe) yyerror("cannot import unsafe package \"%Z\"", importpkg->path); } @@ -536,7 +537,10 @@ compound_stmt: } stmt_list '}' { - $$ = liststmt($3); + if($3 == nil) + $$ = nod(OEMPTY, N, N); + else + $$ = liststmt($3); popdcl(); } diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c index 1cc13a304..f77b51d70 100644 --- a/src/cmd/gc/inl.c +++ b/src/cmd/gc/inl.c @@ -188,6 +188,7 @@ ishairy(Node *n, int *budget) break; case OCLOSURE: + case OCALLPART: case ORANGE: case OFOR: case OSELECT: @@ -357,7 +358,7 @@ inlnode(Node **np) } case OCLOSURE: - // TODO do them here (or earlier) instead of in walkcallclosure, + // TODO do them here (or earlier), // so escape analysis can avoid more heapmoves. return; } @@ -565,24 +566,31 @@ mkinlcall1(Node **np, Node *fn, int isddd) inlretvars = nil; i = 0; // Make temp names to use instead of the originals - for(ll = dcl; ll; ll=ll->next) + for(ll = dcl; ll; ll=ll->next) { + if(ll->n->class == PPARAMOUT) // return values handled below. + continue; if(ll->n->op == ONAME) { ll->n->inlvar = inlvar(ll->n); // Typecheck because inlvar is not necessarily a function parameter. typecheck(&ll->n->inlvar, Erv); if ((ll->n->class&~PHEAP) != PAUTO) ninit = list(ninit, nod(ODCL, ll->n->inlvar, N)); // otherwise gen won't emit the allocations for heapallocs - if (ll->n->class == PPARAMOUT) // we rely on the order being correct here - inlretvars = list(inlretvars, ll->n->inlvar); } + } - // anonymous return values, synthesize names for use in assignment that replaces return - if(inlretvars == nil && fn->type->outtuple > 0) - for(t = getoutargx(fn->type)->type; t; t = t->down) { + // temporaries for return values. + for(t = getoutargx(fn->type)->type; t; t = t->down) { + if(t != T && t->nname != N && !isblank(t->nname)) { + m = inlvar(t->nname); + typecheck(&m, Erv); + t->nname->inlvar = m; + } else { + // anonymous return values, synthesize names for use in assignment that replaces return m = retvar(t, i++); - ninit = list(ninit, nod(ODCL, m, N)); - inlretvars = list(inlretvars, m); } + ninit = list(ninit, nod(ODCL, m, N)); + inlretvars = list(inlretvars, m); + } // assign receiver. if(fn->type->thistuple && n->left->op == ODOTMETH) { @@ -790,6 +798,12 @@ inlvar(Node *var) n->class = PAUTO; n->used = 1; n->curfn = curfn; // the calling function, not the called one + + // esc pass wont run if we're inlining into a iface wrapper + // luckily, we can steal the results from the target func + if(var->esc == EscHeap) + addrescapes(n); + curfn->dcl = list(curfn->dcl, n); return n; } diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c index 68ae6864d..b7f71d553 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 } @@ -601,7 +602,7 @@ void importfile(Val *f, int line) { Biobuf *imp; - char *file, *p, *q; + char *file, *p, *q, *tag; int32 c; int len; Strlit *path; @@ -609,8 +610,6 @@ importfile(Val *f, int line) USED(line); - // TODO(rsc): don't bother reloading imports more than once? - if(f->ctype != CTSTR) { yyerror("import statement not a string"); fakeimport(); @@ -685,7 +684,11 @@ importfile(Val *f, int line) // to the lexer to avoid parsing export data twice. if(importpkg->imported) { file = strdup(namebuf); - p = smprint("package %s\n$$\n", importpkg->name); + tag = ""; + if(importpkg->safe) { + tag = "safe"; + } + p = smprint("package %s %s\n$$\n", importpkg->name, tag); cannedimports(file, p); return; } diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin index 2f76e6f06..1dab1c9a0 100755 --- a/src/cmd/gc/mkbuiltin +++ b/src/cmd/gc/mkbuiltin @@ -19,6 +19,7 @@ fi GC=${GOCHAR}g gcc -o mkbuiltin1 mkbuiltin1.c rm -f _builtin.c +echo "// AUTO-GENERATED by mkbuiltin; DO NOT EDIT" >>_builtin.c for i in runtime unsafe do go tool $GC -A $i.go diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c index b87d35b7b..e4bcd1170 100644 --- a/src/cmd/gc/obj.c +++ b/src/cmd/gc/obj.c @@ -16,6 +16,8 @@ static void dumpglobls(void); void dumpobj(void) { + NodeList *externs, *tmp; + bout = Bopen(outfile, OWRITE); if(bout == nil) { flusherrors(); @@ -31,8 +33,20 @@ dumpobj(void) outhist(bout); + externs = nil; + if(externdcl != nil) + externs = externdcl->end; + dumpglobls(); dumptypestructs(); + + // Dump extra globals. + tmp = externdcl; + if(externs != nil) + externdcl = externs->next; + dumpglobls(); + externdcl = tmp; + dumpdata(); dumpfuncs(); diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c index df8903baf..82d8186b0 100644 --- a/src/cmd/gc/pgen.c +++ b/src/cmd/gc/pgen.c @@ -177,8 +177,13 @@ cmpstackvar(Node *a, Node *b) { if (a->class != b->class) return (a->class == PAUTO) ? 1 : -1; - if (a->class != PAUTO) - return a->xoffset - b->xoffset; + if (a->class != PAUTO) { + if (a->xoffset < b->xoffset) + return -1; + if (a->xoffset > b->xoffset) + return 1; + return 0; + } if ((a->used == 0) != (b->used == 0)) return b->used - a->used; return b->type->align - a->type->align; @@ -240,6 +245,10 @@ allocauto(Prog* ptxt) stksize = rnd(stksize, n->type->align); if(thechar == '5') stksize = rnd(stksize, widthptr); + if(stksize >= (1ULL<<31)) { + setlineno(curfn); + yyerror("stack frame too large (>2GB)"); + } n->stkdelta = -stksize - n->xoffset; } diff --git a/src/cmd/gc/racewalk.c b/src/cmd/gc/racewalk.c index bae98ec1b..5d4f62e76 100644 --- a/src/cmd/gc/racewalk.c +++ b/src/cmd/gc/racewalk.c @@ -26,6 +26,7 @@ static Node* uintptraddr(Node *n); static Node* basenod(Node *n); static void foreach(Node *n, void(*f)(Node*, void*), void *c); static void hascallspred(Node *n, void *c); +static void appendinit(Node **np, NodeList *init); static Node* detachexpr(Node *n, NodeList **init); // Do not instrument the following packages at all, @@ -132,14 +133,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) case OASOP: case OAS: case OAS2: - case OAS2DOTTYPE: case OAS2RECV: case OAS2FUNC: case OAS2MAPR: racewalknode(&n->left, init, 1, 0); racewalknode(&n->right, init, 0, 0); goto ret; - + case OCFUNC: // can't matter goto ret; @@ -185,17 +185,12 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) racewalknode(&n->left, init, 0, 0); goto ret; - case OSWITCH: - if(n->ntest->op == OTYPESW) - // TODO(dvyukov): the expression can contain calls or reads. - return; - goto ret; - case ONOT: case OMINUS: case OPLUS: case OREAL: case OIMAG: + case OCOM: racewalknode(&n->left, init, wr, 0); goto ret; @@ -222,29 +217,24 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) case OCAP: racewalknode(&n->left, init, 0, 0); if(istype(n->left->type, TMAP)) { - // crashes on len(m[0]) or len(f()) - SET(n1); - USED(n1); - /* - n1 = nod(OADDR, n->left, N); - n1 = conv(n1, types[TUNSAFEPTR]); - n1 = conv(n1, ptrto(ptrto(types[TINT8]))); - n1 = nod(OIND, n1, N); + n1 = nod(OCONVNOP, n->left, N); + n1->type = ptrto(types[TUINT8]); n1 = nod(OIND, n1, N); typecheck(&n1, Erv); callinstr(&n1, init, 0, skip); - */ } goto ret; case OLSH: case ORSH: + case OLROT: case OAND: case OANDNOT: case OOR: case OXOR: case OSUB: case OMUL: + case OHMUL: case OEQ: case ONE: case OLT: @@ -260,9 +250,13 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) case OANDAND: case OOROR: racewalknode(&n->left, init, wr, 0); - // It requires more complex tree transformation, - // because we don't know whether it will be executed or not. - //racewalknode(&n->right, init, wr, 0); + // walk has ensured the node has moved to a location where + // side effects are safe. + // n->right may not be executed, + // so instrumentation goes to n->right->ninit, not init. + l = nil; + racewalknode(&n->right, &l, wr, 0); + appendinit(&n->right, l); goto ret; case ONAME: @@ -279,7 +273,6 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) case ODIV: case OMOD: - // TODO(dvyukov): add a test for this racewalknode(&n->left, init, wr, 0); racewalknode(&n->right, init, wr, 0); goto ret; @@ -313,6 +306,14 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) racewalknode(&n->right, init, 0, 0); goto ret; + case OITAB: + racewalknode(&n->left, init, 0, 0); + goto ret; + + case OTYPESW: + racewalknode(&n->right, init, 0, 0); + goto ret; + // should not appear in AST by now case OSEND: case ORECV: @@ -324,67 +325,69 @@ racewalknode(Node **np, NodeList **init, int wr, int skip) case OPANIC: case ORECOVER: case OCONVIFACE: + case OCMPIFACE: + case OMAKECHAN: + case OMAKEMAP: + case OMAKESLICE: + case OCALL: + case OCOPY: + case OAPPEND: + case ORUNESTR: + case OARRAYBYTESTR: + case OARRAYRUNESTR: + case OSTRARRAYBYTE: + case OSTRARRAYRUNE: + case OINDEXMAP: // lowered to call + case OCMPSTR: + case OADDSTR: + case ODOTTYPE: + case ODOTTYPE2: + case OAS2DOTTYPE: + case OCALLPART: // lowered to PTRLIT + case OCLOSURE: // lowered to PTRLIT + case ORANGE: // lowered to ordinary for loop + case OARRAYLIT: // lowered to assignments + case OMAPLIT: + case OSTRUCTLIT: yyerror("racewalk: %O must be lowered by now", n->op); goto ret; + // impossible nodes: only appear in backend. + case ORROTC: + case OEXTEND: + yyerror("racewalk: %O cannot exist now", n->op); + goto ret; + // just do generic traversal case OFOR: case OIF: case OCALLMETH: case ORETURN: + case OSWITCH: case OSELECT: case OEMPTY: + case OBREAK: + case OCONTINUE: + case OFALL: + case OGOTO: + case OLABEL: goto ret; // does not require instrumentation - case OINDEXMAP: // implemented in runtime case OPRINT: // don't bother instrumenting it case OPRINTN: // don't bother instrumenting it + case OCHECKNOTNIL: // always followed by a read. case OPARAM: // it appears only in fn->exit to copy heap params back - goto ret; - - // unimplemented - case OCMPSTR: - case OADDSTR: - case OSLICESTR: - case OAPPEND: - case OCOPY: - case OMAKECHAN: - case OMAKEMAP: - case OMAKESLICE: - case ORUNESTR: - case OARRAYBYTESTR: - case OARRAYRUNESTR: - case OSTRARRAYBYTE: - case OSTRARRAYRUNE: - case OCMPIFACE: - case OARRAYLIT: - case OMAPLIT: - case OSTRUCTLIT: - case OCLOSURE: - case ODOTTYPE: - case ODOTTYPE2: - case OCALL: - case OBREAK: - case ODCL: - case OCONTINUE: - case OFALL: - case OGOTO: - case OLABEL: + case OCLOSUREVAR:// immutable pointer to captured variable + case ODOTMETH: // either part of CALLMETH or CALLPART (lowered to PTRLIT) + case OINDREG: // at this stage, only n(SP) nodes from nodarg + case ODCL: // declarations (without value) cannot be races case ODCLCONST: case ODCLTYPE: - case OLITERAL: - case ORANGE: case OTYPE: case ONONAME: - case OINDREG: - case OCOM: - case ODOTMETH: - case OITAB: - case OEXTEND: - case OHMUL: - case OLROT: - case ORROTC: + case OLITERAL: + case OSLICESTR: // always preceded by bounds checking, avoid double instrumentation. goto ret; } @@ -400,7 +403,6 @@ ret: racewalklist(n->nbody, nil); racewalklist(n->nelse, nil); racewalklist(n->rlist, nil); - *np = n; } @@ -442,6 +444,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip) if(isartificial(n)) return 0; if(t->etype == TSTRUCT) { + // TODO: instrument arrays similarly. // PARAMs w/o PHEAP are not interesting. if(n->class == PPARAM || n->class == PPARAMOUT) return 0; @@ -478,7 +481,7 @@ callinstr(Node **np, NodeList **init, int wr, int skip) // that has got a pointer inside. Whether it points to // the heap or not is impossible to know at compile time if((class&PHEAP) || class == PPARAMREF || class == PEXTERN - || b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) { + || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) { hascalls = 0; foreach(n, hascallspred, &hascalls); if(hascalls) { @@ -504,6 +507,8 @@ uintptraddr(Node *n) return r; } +// basenod returns the simplest child node of n pointing to the same +// memory area. static Node* basenod(Node *n) { @@ -512,7 +517,7 @@ basenod(Node *n) n = n->left; continue; } - if(n->op == OINDEX) { + if(n->op == OINDEX && isfixedarray(n->type)) { n = n->left; continue; } @@ -577,3 +582,30 @@ hascallspred(Node *n, void *c) (*(int*)c)++; } } + +// appendinit is like addinit in subr.c +// but appends rather than prepends. +static void +appendinit(Node **np, NodeList *init) +{ + Node *n; + + if(init == nil) + return; + + n = *np; + switch(n->op) { + case ONAME: + case OLITERAL: + // There may be multiple refs to this node; + // introduce OCONVNOP to hold init list. + n = nod(OCONVNOP, n, N); + n->type = n->left->type; + n->typecheck = 1; + *np = n; + break; + } + n->ninit = concat(n->ninit, init); + n->ullman = UINF; +} + diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index 50c4617c0..8af45b9d2 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -181,9 +181,9 @@ walkrange(Node *n) case TMAP: th = typ(TARRAY); th->type = ptrto(types[TUINT8]); - // see ../../pkg/runtime/hashmap.h:/hash_iter - // Size in words. - th->bound = 5 + 4*3 + 4*4/widthptr; + // see ../../pkg/runtime/hashmap.c:/hash_iter + // Size of hash_iter in # of pointers. + th->bound = 11; hit = temp(th); fn = syslook("mapiterinit", 1); diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index b8eb79938..fc182b03e 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -1026,13 +1026,29 @@ dalgsym(Type *t) } static int +gcinline(Type *t) { + switch(t->etype) { + case TARRAY: + if(t->bound == 1) + return 1; + if(t->width <= 4*widthptr) + return 1; + break; + } + return 0; +} + +static int dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) { Type *t1; - vlong o, off2, fieldoffset; + vlong o, off2, fieldoffset, i; if(t->align > 0 && (*off % t->align) != 0) fatal("dgcsym1: invalid initial alignment, %T", t); + + if(t->width == BADWIDTH) + dowidth(t); switch(t->etype) { case TINT8: @@ -1056,6 +1072,7 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) case TPTR32: case TPTR64: + // NOTE: Any changes here need to be made to reflect.PtrTo as well. if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); if(!haspointers(t->type) || t->type->etype == TUINT8) { @@ -1069,7 +1086,6 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) *off += t->width; break; - case TCHAN: case TUNSAFEPTR: case TFUNC: if(*off % widthptr != 0) @@ -1079,8 +1095,20 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) *off += t->width; break; + // struct Hchan* + case TCHAN: + // NOTE: Any changes here need to be made to reflect.ChanOf as well. + if(*off % widthptr != 0) + fatal("dgcsym1: invalid alignment, %T", t); + ot = duintptr(s, ot, GC_CHAN_PTR); + ot = duintptr(s, ot, *off); + ot = dsymptr(s, ot, dtypesym(t), 0); + *off += t->width; + break; + // struct Hmap* case TMAP: + // NOTE: Any changes here need to be made to reflect.MapOf as well. if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); ot = duintptr(s, ot, GC_MAP_PTR); @@ -1116,7 +1144,10 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) case TARRAY: if(t->bound < -1) fatal("dgcsym1: invalid bound, %T", t); + if(t->type->width == BADWIDTH) + dowidth(t->type); if(isslice(t)) { + // NOTE: Any changes here need to be made to reflect.SliceOf as well. // struct { byte* array; uint32 len; uint32 cap; } if(*off % widthptr != 0) fatal("dgcsym1: invalid alignment, %T", t); @@ -1130,10 +1161,14 @@ dgcsym1(Sym *s, int ot, Type *t, vlong *off, int stack_size) } *off += t->width; } else { + // NOTE: Any changes here need to be made to reflect.ArrayOf as well, + // at least once ArrayOf's gc info is implemented and ArrayOf is exported. + // struct { byte* array; uint32 len; uint32 cap; } if(t->bound < 1 || !haspointers(t->type)) { *off += t->width; - } else if(t->bound == 1) { - ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 + } else if(gcinline(t)) { + for(i=0; i<t->bound; i++) + ot = dgcsym1(s, ot, t->type, off, stack_size); // recursive call of dgcsym1 } else { if(stack_size < GC_STACK_CAPACITY) { ot = duintptr(s, ot, GC_ARRAY_START); // a stack push during GC @@ -1184,6 +1219,9 @@ dgcsym(Type *t) return s; s->flags |= SymGcgen; + if(t->width == BADWIDTH) + dowidth(t); + ot = 0; off = 0; ot = duintptr(s, ot, t->width); diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index c49d05c5c..2139a95d9 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -89,7 +89,13 @@ func equal(typ *byte, x1, x2 any) (ret bool) // *byte is really *runtime.Type func makemap(mapType *byte, hint int64) (hmap map[any]any) func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any) +func mapaccess1_fast32(mapType *byte, hmap map[any]any, key any) (val *any) +func mapaccess1_fast64(mapType *byte, hmap map[any]any, key any) (val *any) +func mapaccess1_faststr(mapType *byte, hmap map[any]any, key any) (val *any) func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool) +func mapaccess2_fast32(mapType *byte, hmap map[any]any, key any) (val *any, pres bool) +func mapaccess2_fast64(mapType *byte, hmap map[any]any, key any) (val *any, pres bool) +func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pres bool) func mapassign1(mapType *byte, hmap map[any]any, key any, val any) func mapiterinit(mapType *byte, hmap map[any]any, hiter *any) func mapdelete(mapType *byte, hmap map[any]any, key any) diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 353fc00ce..f8c61828c 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -801,7 +801,8 @@ maplit(int ctxt, Node *n, Node *var, NodeList **init) { Node *r, *a; NodeList *l; - int nerr, b; + int nerr; + int64 b; Type *t, *tk, *tv, *t1; Node *vstat, *index, *value; Sym *syma, *symb; @@ -1142,7 +1143,10 @@ stataddr(Node *nam, Node *n) l = getlit(n->right); if(l < 0) break; - nam->xoffset += l*n->type->width; + // Check for overflow. + if(n->type->width != 0 && MAXWIDTH/n->type->width <= l) + break; + nam->xoffset += l*n->type->width; nam->type = n->type; return 1; } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index c53eaf285..20a15bc71 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -548,6 +548,12 @@ algtype1(Type *t, Type **bad) *bad = T; switch(t->etype) { + case TANY: + case TFORW: + // will be defined later. + *bad = t; + return -1; + case TINT8: case TUINT8: case TINT16: @@ -665,11 +671,14 @@ Type* maptype(Type *key, Type *val) { Type *t; + Type *bad; + int atype; if(key != nil) { - switch(key->etype) { + atype = algtype1(key, &bad); + switch(bad == T ? key->etype : bad->etype) { default: - if(algtype1(key, nil) == ANOEQ) + if(atype == ANOEQ) yyerror("invalid map key type %T", key); break; case TANY: @@ -714,6 +723,12 @@ methcmp(const void *va, const void *vb) a = *(Type**)va; b = *(Type**)vb; + if(a->sym == S && b->sym == S) + return 0; + if(a->sym == S) + return -1; + if(b->sym == S) + return 1; i = strcmp(a->sym->name, b->sym->name); if(i != 0) return i; @@ -824,7 +839,7 @@ Type* aindex(Node *b, Type *t) { Type *r; - int bound; + int64 bound; bound = -1; // open bound typecheck(&b, Erv); @@ -1393,7 +1408,7 @@ assignconv(Node *n, Type *t, char *context) Node *r, *old; char *why; - if(n == N || n->type == T) + if(n == N || n->type == T || n->type->broke) return n; old = n; @@ -1759,6 +1774,13 @@ ullmancalc(Node *n) case OCALLINTER: ul = UINF; goto out; + case OANDAND: + case OOROR: + // hard with race detector + if(flag_race) { + ul = UINF; + goto out; + } } ul = 1; if(n->left != N) @@ -1772,6 +1794,8 @@ ullmancalc(Node *n) ul = ur; out: + if(ul > 200) + ul = 200; // clamp to uchar with room to grow n->ullman = ul; } @@ -2096,7 +2120,7 @@ localexpr(Node *n, Type *t, NodeList **init) void setmaxarg(Type *t) { - int32 w; + int64 w; dowidth(t); w = t->argwid; @@ -2565,6 +2589,7 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) fn->dupok = 1; typecheck(&fn, Etop); typechecklist(fn->nbody, Etop); + inlcalls(fn); curfn = nil; funccompile(fn, 0); } @@ -3273,11 +3298,14 @@ liststmt(NodeList *l) int count(NodeList *l) { - int n; + vlong n; n = 0; for(; l; l=l->next) n++; + if((int)n != n) { // Overflow. + yyerror("too many elements in list"); + } return n; } @@ -3722,3 +3750,17 @@ isbadimport(Strlit *path) } return 0; } + +void +checknotnil(Node *x, NodeList **init) +{ + Node *n; + + if(isinter(x->type)) { + x = nod(OITAB, x, N); + typecheck(&x, Erv); + } + n = nod(OCHECKNOTNIL, x, N); + n->typecheck = 1; + *init = list(*init, n); +} diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index a497b8622..3ad5f02a5 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -322,6 +322,10 @@ casebody(Node *sw, Node *typeswvar) setlineno(last); yyerror("cannot fallthrough in type switch"); } + if(l->next == nil) { + setlineno(last); + yyerror("cannot fallthrough final case in switch"); + } last->op = OFALL; } else stat = list(stat, br); @@ -354,6 +358,8 @@ mkcaselist(Node *sw, int arg) c = c1; ord++; + if((uint16)ord != ord) + fatal("too many cases in switch"); c->ordinal = ord; c->node = n; diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index fbab85d03..40eecd337 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -276,6 +276,29 @@ callrecvlist(NodeList *l) return 0; } +// indexlit implements typechecking of untyped values as +// array/slice indexes. It is equivalent to defaultlit +// except for constants of numerical kind, which are acceptable +// whenever they can be represented by a value of type int. +static void +indexlit(Node **np) +{ + Node *n; + + n = *np; + if(n == N || !isideal(n->type)) + return; + switch(consttype(n)) { + case CTINT: + case CTRUNE: + case CTFLT: + case CTCPLX: + defaultlit(np, types[TINT]); + break; + } + defaultlit(np, T); +} + static void typecheck1(Node **np, int top) { @@ -732,6 +755,7 @@ reswitch: yyerror("rhs of . must be a name"); // impossible goto error; } + r = n->right; if(n->left->op == OTYPE) { if(!looktypedot(n, t, 0)) { @@ -775,7 +799,12 @@ reswitch: switch(n->op) { case ODOTINTER: case ODOTMETH: - ok |= Ecall; + if(top&Ecall) + ok |= Ecall; + else { + typecheckpartialcall(n, r); + ok |= Erv; + } break; default: ok |= Erv; @@ -839,7 +868,7 @@ reswitch: case TSTRING: case TARRAY: - defaultlit(&n->right, T); + indexlit(&n->right); if(t->etype == TSTRING) n->type = types[TUINT8]; else @@ -855,8 +884,8 @@ reswitch: yyerror("non-integer %s index %N", why, n->right); break; } - if(n->right->op == OLITERAL) { - if(mpgetfix(n->right->val.u.xval) < 0) + if(isconst(n->right, CTINT)) { + if(mpgetfix(n->right->val.u.xval) < 0) yyerror("invalid %s index %N (index must be non-negative)", why, n->right); else if(isfixedarray(t) && t->bound > 0 && mpgetfix(n->right->val.u.xval) >= t->bound) yyerror("invalid array index %N (out of bounds for %d-element array)", n->right, t->bound); @@ -932,8 +961,8 @@ reswitch: typecheck(&n->right->left, Erv); typecheck(&n->right->right, Erv); defaultlit(&n->left, T); - defaultlit(&n->right->left, T); - defaultlit(&n->right->right, T); + indexlit(&n->right->left); + indexlit(&n->right->right); l = n->left; if(isfixedarray(l->type)) { if(!islvalue(n->left)) { @@ -1180,16 +1209,18 @@ reswitch: if(l->type == T || r->type == T) goto error; defaultlit2(&l, &r, 0); + if(l->type == T || r->type == T) + goto error; n->left = l; n->right = r; - if(l->type->etype != r->type->etype) { - badcmplx: - yyerror("invalid operation: %N (complex of types %T, %T)", n, l->type, r->type); + if(!eqtype(l->type, r->type)) { + yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type); goto error; } switch(l->type->etype) { default: - goto badcmplx; + yyerror("invalid operation: %N (arguments have type %T, expected floating-point)", n, l->type, r->type); + goto error; case TIDEAL: t = types[TIDEAL]; break; @@ -1692,10 +1723,6 @@ ret: yyerror("%N is not a type", n); goto error; } - if((ok & Ecall) && !(top & Ecall)) { - yyerror("method %N is not an expression, must be called", n); - goto error; - } // TODO(rsc): simplify if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) { yyerror("%N used as value", n); @@ -2323,7 +2350,8 @@ pushtype(Node *n, Type *t) static void typecheckcomplit(Node **np) { - int bad, i, len, nerr; + int bad, i, nerr; + int64 len; Node *l, *n, *norig, *r, **hash; NodeList *ll; Type *t, *f; @@ -2558,6 +2586,7 @@ islvalue(Node *n) // fall through case OIND: case ODOTPTR: + case OCLOSUREVAR: return 1; case ODOT: return islvalue(n->left); @@ -3144,3 +3173,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/unsafe.c b/src/cmd/gc/unsafe.c index 95200ad41..ff08c0eef 100644 --- a/src/cmd/gc/unsafe.c +++ b/src/cmd/gc/unsafe.c @@ -16,10 +16,10 @@ Node* unsafenmagic(Node *nn) { - Node *r, *n; + Node *r, *n, *base, *r1; Sym *s; Type *t, *tr; - long v; + vlong v; Val val; Node *fn; NodeList *args; @@ -49,11 +49,43 @@ unsafenmagic(Node *nn) goto yes; } if(strcmp(s->name, "Offsetof") == 0) { - typecheck(&r, Erv); - if(r->op != ODOT && r->op != ODOTPTR) + // must be a selector. + if(r->op != OXDOT) goto bad; + // Remember base of selector to find it back after dot insertion. + // Since r->left may be mutated by typechecking, check it explicitly + // first to track it correctly. + typecheck(&r->left, Erv); + base = r->left; typecheck(&r, Erv); - v = r->xoffset; + switch(r->op) { + case ODOT: + case ODOTPTR: + break; + case OCALLPART: + yyerror("invalid expression %N: argument is a method value", nn); + v = 0; + goto ret; + default: + goto bad; + } + v = 0; + // add offsets for inserted dots. + for(r1=r; r1->left!=base; r1=r1->left) { + switch(r1->op) { + case ODOT: + v += r1->xoffset; + break; + case ODOTPTR: + yyerror("invalid expression %N: selector implies indirection of embedded %N", nn, r1->left); + goto ret; + default: + dump("unsafenmagic", r); + fatal("impossible %#O node after dot insertion", r1->op); + goto bad; + } + } + v += r1->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index de2105ed3..d9c6341b4 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; @@ -221,6 +184,7 @@ walkstmt(Node **np) case OLABEL: case ODCLCONST: case ODCLTYPE: + case OCHECKNOTNIL: break; case OBLOCK: @@ -433,13 +397,28 @@ walkexpr(Node **np, NodeList **init) case OIMAG: case ODOTMETH: case ODOTINTER: + walkexpr(&n->left, init); + goto ret; + case OIND: + if(n->left->type->type->width == 0) { + n->left = cheapexpr(n->left, init); + checknotnil(n->left, init); + } walkexpr(&n->left, init); goto ret; case ODOT: + usefield(n); + walkexpr(&n->left, init); + goto ret; + case ODOTPTR: usefield(n); + if(n->op == ODOTPTR && n->left->type->type->width == 0) { + n->left = cheapexpr(n->left, init); + checknotnil(n->left, init); + } walkexpr(&n->left, init); goto ret; @@ -561,13 +540,6 @@ walkexpr(Node **np, NodeList **init) if(n->list && n->list->n->op == OAS) goto ret; - /* - if(n->left->op == OCLOSURE) { - walkcallclosure(n, init); - t = n->left->type; - } - */ - walkexpr(&n->left, init); walkexprlist(n->list, init); @@ -673,8 +645,48 @@ walkexpr(Node **np, NodeList **init) r = n->rlist->n; walkexprlistsafe(n->list, init); walkexpr(&r->left, init); - fn = mapfn("mapaccess2", r->left->type); - r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right); + t = r->left->type; + p = nil; + if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. + switch(simsimtype(t->down)) { + case TINT32: + case TUINT32: + p = "mapaccess2_fast32"; + break; + case TINT64: + case TUINT64: + p = "mapaccess2_fast64"; + break; + case TSTRING: + p = "mapaccess2_faststr"; + break; + } + } + if(p != nil) { + // from: + // a,b = m[i] + // to: + // var,b = mapaccess2_fast*(t, m, i) + // a = *var + a = n->list->n; + var = temp(ptrto(t->type)); + var->typecheck = 1; + + fn = mapfn(p, t); + r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right); + n->rlist = list1(r); + n->op = OAS2FUNC; + n->list->n = var; + walkexpr(&n, init); + *init = list(*init, n); + + n = nod(OAS, a, nod(OIND, var, N)); + typecheck(&n, Etop); + walkexpr(&n, init); + goto ret; + } + fn = mapfn("mapaccess2", t); + r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, r->right); n->rlist = list1(r); n->op = OAS2FUNC; goto as2func; @@ -1041,7 +1053,33 @@ walkexpr(Node **np, NodeList **init) goto ret; t = n->left->type; - n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right); + p = nil; + if(t->type->width <= 128) { // Check ../../pkg/runtime/hashmap.c:MAXVALUESIZE before changing. + switch(simsimtype(t->down)) { + case TINT32: + case TUINT32: + p = "mapaccess1_fast32"; + break; + case TINT64: + case TUINT64: + p = "mapaccess1_fast64"; + break; + case TSTRING: + p = "mapaccess1_faststr"; + break; + } + } + if(p != nil) { + // use fast version. The fast versions return a pointer to the value - we need + // to dereference it to get the result. + n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, n->right); + n = nod(OIND, n, N); + n->type = t->type; + n->typecheck = 1; + } else { + // no fast version for this key + n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right); + } goto ret; case ORECV: @@ -1292,6 +1330,10 @@ walkexpr(Node **np, NodeList **init) case OCLOSURE: n = walkclosure(n, init); goto ret; + + case OCALLPART: + n = walkpartialcall(n, init); + goto ret; } fatal("missing switch %O", n->op); @@ -2814,11 +2856,19 @@ walkcompare(Node **np, NodeList **init) typecheck(&call, Etop); walkstmt(&call); *init = list(*init, call); - - if(n->op == OEQ) - r = tempbool; - else - r = nod(ONOT, tempbool, N); + + // tempbool cannot be used directly as multiple comparison + // expressions may exist in the same statement. Create another + // temporary to hold the value (its address is not taken so it can + // be optimized away). + r = temp(types[TBOOL]); + a = nod(OAS, r, tempbool); + typecheck(&a, Etop); + walkstmt(&a); + *init = list(*init, a); + + if(n->op != OEQ) + r = nod(ONOT, r, N); typecheck(&r, Erv); walkexpr(&r, init); *np = r; @@ -2847,14 +2897,29 @@ hard: static int samecheap(Node *a, Node *b) { - if(a == N || b == N || a->op != b->op) - return 0; - - switch(a->op) { - case ONAME: - return a == b; - // TODO: Could do more here, but maybe this is enough. - // It's all cheapexpr does. + Node *ar, *br; + while(a != N && b != N && a->op == b->op) { + switch(a->op) { + default: + return 0; + case ONAME: + return a == b; + case ODOT: + case ODOTPTR: + ar = a->right; + br = b->right; + if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym) + return 0; + break; + case OINDEX: + ar = a->right; + br = b->right; + if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0) + return 0; + break; + } + a = a->left; + b = b->left; } return 0; } diff --git a/src/cmd/gc/y.tab.c b/src/cmd/gc/y.tab.c index 75175455e..21c67e805 100644 --- a/src/cmd/gc/y.tab.c +++ b/src/cmd/gc/y.tab.c @@ -658,39 +658,39 @@ static const yytype_uint16 yyrline[] = { 0, 124, 124, 133, 140, 151, 151, 166, 167, 170, 171, 172, 175, 208, 219, 220, 223, 230, 237, 246, - 259, 260, 267, 267, 280, 284, 285, 289, 294, 300, - 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 + 260, 261, 268, 268, 281, 285, 286, 290, 295, 301, + 305, 309, 313, 319, 325, 331, 336, 340, 344, 350, + 356, 360, 364, 370, 374, 380, 381, 385, 391, 400, + 406, 424, 429, 441, 457, 462, 469, 489, 507, 516, + 535, 534, 549, 548, 579, 582, 589, 588, 599, 605, + 614, 625, 631, 634, 642, 641, 652, 658, 670, 674, + 679, 669, 700, 699, 712, 715, 721, 724, 736, 740, + 735, 758, 757, 773, 774, 778, 782, 786, 790, 794, + 798, 802, 806, 810, 814, 818, 822, 826, 830, 834, + 838, 842, 846, 851, 857, 858, 862, 873, 877, 881, + 885, 890, 894, 904, 908, 913, 921, 925, 926, 937, + 941, 945, 949, 953, 954, 960, 967, 973, 980, 983, + 990, 996, 1013, 1020, 1021, 1028, 1029, 1048, 1049, 1052, + 1055, 1059, 1070, 1079, 1085, 1088, 1091, 1098, 1099, 1105, + 1120, 1128, 1140, 1145, 1151, 1152, 1153, 1154, 1155, 1156, + 1162, 1163, 1164, 1165, 1171, 1172, 1173, 1174, 1175, 1181, + 1182, 1185, 1188, 1189, 1190, 1191, 1192, 1195, 1196, 1209, + 1213, 1218, 1223, 1228, 1232, 1233, 1236, 1242, 1249, 1255, + 1262, 1268, 1279, 1293, 1322, 1362, 1387, 1405, 1414, 1417, + 1425, 1429, 1433, 1440, 1446, 1451, 1463, 1466, 1476, 1477, + 1483, 1484, 1490, 1494, 1500, 1501, 1507, 1511, 1517, 1540, + 1545, 1551, 1557, 1564, 1573, 1582, 1597, 1603, 1608, 1612, + 1619, 1632, 1633, 1639, 1645, 1648, 1652, 1658, 1661, 1670, + 1673, 1674, 1678, 1679, 1685, 1686, 1687, 1688, 1689, 1691, + 1690, 1705, 1710, 1714, 1718, 1722, 1726, 1731, 1750, 1756, + 1764, 1768, 1774, 1778, 1784, 1788, 1794, 1798, 1807, 1811, + 1815, 1819, 1825, 1828, 1836, 1837, 1839, 1840, 1843, 1846, + 1849, 1852, 1855, 1858, 1861, 1864, 1867, 1870, 1873, 1876, + 1879, 1882, 1888, 1892, 1896, 1900, 1904, 1908, 1928, 1935, + 1946, 1947, 1948, 1951, 1952, 1955, 1959, 1969, 1973, 1977, + 1981, 1985, 1989, 1993, 1999, 2005, 2013, 2021, 2027, 2034, + 2050, 2068, 2072, 2078, 2081, 2084, 2088, 2098, 2102, 2117, + 2125, 2126, 2138, 2139, 2142, 2146, 2152, 2156, 2162, 2166 }; #endif @@ -2494,14 +2494,15 @@ yyreduce: } else if(strcmp(importpkg->name, (yyvsp[(2) - (4)].sym)->name) != 0) yyerror("conflicting names %s and %s for package \"%Z\"", importpkg->name, (yyvsp[(2) - (4)].sym)->name, importpkg->path); importpkg->direct = 1; - + importpkg->safe = curio.importsafe; + if(safemode && !curio.importsafe) yyerror("cannot import unsafe package \"%Z\"", importpkg->path); } break; case 21: -#line 261 "go.y" +#line 262 "go.y" { if(strcmp((yyvsp[(1) - (1)].sym)->name, "safe") == 0) curio.importsafe = 1; @@ -2509,14 +2510,14 @@ yyreduce: break; case 22: -#line 267 "go.y" +#line 268 "go.y" { defercheckwidth(); } break; case 23: -#line 271 "go.y" +#line 272 "go.y" { resumecheckwidth(); unimportfile(); @@ -2524,7 +2525,7 @@ yyreduce: break; case 24: -#line 280 "go.y" +#line 281 "go.y" { yyerror("empty top-level declaration"); (yyval.list) = nil; @@ -2532,14 +2533,14 @@ yyreduce: break; case 26: -#line 286 "go.y" +#line 287 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 27: -#line 290 "go.y" +#line 291 "go.y" { yyerror("non-declaration statement outside function body"); (yyval.list) = nil; @@ -2547,35 +2548,35 @@ yyreduce: break; case 28: -#line 295 "go.y" +#line 296 "go.y" { (yyval.list) = nil; } break; case 29: -#line 301 "go.y" +#line 302 "go.y" { (yyval.list) = (yyvsp[(2) - (2)].list); } break; case 30: -#line 305 "go.y" +#line 306 "go.y" { (yyval.list) = (yyvsp[(3) - (5)].list); } break; case 31: -#line 309 "go.y" +#line 310 "go.y" { (yyval.list) = nil; } break; case 32: -#line 313 "go.y" +#line 314 "go.y" { (yyval.list) = (yyvsp[(2) - (2)].list); iota = -100000; @@ -2584,7 +2585,7 @@ yyreduce: break; case 33: -#line 319 "go.y" +#line 320 "go.y" { (yyval.list) = (yyvsp[(3) - (5)].list); iota = -100000; @@ -2593,7 +2594,7 @@ yyreduce: break; case 34: -#line 325 "go.y" +#line 326 "go.y" { (yyval.list) = concat((yyvsp[(3) - (7)].list), (yyvsp[(5) - (7)].list)); iota = -100000; @@ -2602,7 +2603,7 @@ yyreduce: break; case 35: -#line 331 "go.y" +#line 332 "go.y" { (yyval.list) = nil; iota = -100000; @@ -2610,84 +2611,84 @@ yyreduce: break; case 36: -#line 336 "go.y" +#line 337 "go.y" { (yyval.list) = list1((yyvsp[(2) - (2)].node)); } break; case 37: -#line 340 "go.y" +#line 341 "go.y" { (yyval.list) = (yyvsp[(3) - (5)].list); } break; case 38: -#line 344 "go.y" +#line 345 "go.y" { (yyval.list) = nil; } break; case 39: -#line 350 "go.y" +#line 351 "go.y" { iota = 0; } break; case 40: -#line 356 "go.y" +#line 357 "go.y" { (yyval.list) = variter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil); } break; case 41: -#line 360 "go.y" +#line 361 "go.y" { (yyval.list) = variter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list)); } break; case 42: -#line 364 "go.y" +#line 365 "go.y" { (yyval.list) = variter((yyvsp[(1) - (3)].list), nil, (yyvsp[(3) - (3)].list)); } break; case 43: -#line 370 "go.y" +#line 371 "go.y" { (yyval.list) = constiter((yyvsp[(1) - (4)].list), (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].list)); } break; case 44: -#line 374 "go.y" +#line 375 "go.y" { (yyval.list) = constiter((yyvsp[(1) - (3)].list), N, (yyvsp[(3) - (3)].list)); } break; case 46: -#line 381 "go.y" +#line 382 "go.y" { (yyval.list) = constiter((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node), nil); } break; case 47: -#line 385 "go.y" +#line 386 "go.y" { (yyval.list) = constiter((yyvsp[(1) - (1)].list), N, nil); } break; case 48: -#line 391 "go.y" +#line 392 "go.y" { // different from dclname because the name // becomes visible right here, not at the end @@ -2697,14 +2698,14 @@ yyreduce: break; case 49: -#line 400 "go.y" +#line 401 "go.y" { (yyval.node) = typedcl1((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node), 1); } break; case 50: -#line 406 "go.y" +#line 407 "go.y" { (yyval.node) = (yyvsp[(1) - (1)].node); @@ -2725,7 +2726,7 @@ yyreduce: break; case 51: -#line 424 "go.y" +#line 425 "go.y" { (yyval.node) = nod(OASOP, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); (yyval.node)->etype = (yyvsp[(2) - (3)].i); // rathole to pass opcode @@ -2733,7 +2734,7 @@ yyreduce: break; case 52: -#line 429 "go.y" +#line 430 "go.y" { if((yyvsp[(1) - (3)].list)->next == nil && (yyvsp[(3) - (3)].list)->next == nil) { // simple @@ -2748,7 +2749,7 @@ yyreduce: break; case 53: -#line 441 "go.y" +#line 442 "go.y" { if((yyvsp[(3) - (3)].list)->n->op == OTYPESW) { (yyval.node) = nod(OTYPESW, N, (yyvsp[(3) - (3)].list)->n->right); @@ -2767,7 +2768,7 @@ yyreduce: break; case 54: -#line 457 "go.y" +#line 458 "go.y" { (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1)); (yyval.node)->etype = OADD; @@ -2775,7 +2776,7 @@ yyreduce: break; case 55: -#line 462 "go.y" +#line 463 "go.y" { (yyval.node) = nod(OASOP, (yyvsp[(1) - (2)].node), nodintconst(1)); (yyval.node)->etype = OSUB; @@ -2783,7 +2784,7 @@ yyreduce: break; case 56: -#line 469 "go.y" +#line 470 "go.y" { Node *n, *nn; @@ -2806,7 +2807,7 @@ yyreduce: break; case 57: -#line 489 "go.y" +#line 490 "go.y" { Node *n; @@ -2827,7 +2828,7 @@ yyreduce: break; case 58: -#line 507 "go.y" +#line 508 "go.y" { // will be converted to OCASE // right will point to next case @@ -2839,7 +2840,7 @@ yyreduce: break; case 59: -#line 516 "go.y" +#line 517 "go.y" { Node *n, *nn; @@ -2858,22 +2859,25 @@ yyreduce: break; case 60: -#line 534 "go.y" +#line 535 "go.y" { markdcl(); } break; case 61: -#line 538 "go.y" +#line 539 "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 549 "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 +2890,7 @@ yyreduce: break; case 63: -#line 555 "go.y" +#line 559 "go.y" { int last; @@ -2908,28 +2912,28 @@ yyreduce: break; case 64: -#line 575 "go.y" +#line 579 "go.y" { (yyval.list) = nil; } break; case 65: -#line 579 "go.y" +#line 583 "go.y" { (yyval.list) = list((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); } break; case 66: -#line 585 "go.y" +#line 589 "go.y" { markdcl(); } break; case 67: -#line 589 "go.y" +#line 593 "go.y" { (yyval.list) = (yyvsp[(3) - (4)].list); popdcl(); @@ -2937,7 +2941,7 @@ yyreduce: break; case 68: -#line 596 "go.y" +#line 600 "go.y" { (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node)); (yyval.node)->list = (yyvsp[(1) - (4)].list); @@ -2946,7 +2950,7 @@ yyreduce: break; case 69: -#line 602 "go.y" +#line 606 "go.y" { (yyval.node) = nod(ORANGE, N, (yyvsp[(4) - (4)].node)); (yyval.node)->list = (yyvsp[(1) - (4)].list); @@ -2956,7 +2960,7 @@ yyreduce: break; case 70: -#line 611 "go.y" +#line 615 "go.y" { // init ; test ; incr if((yyvsp[(5) - (5)].node) != N && (yyvsp[(5) - (5)].node)->colas != 0) @@ -2970,7 +2974,7 @@ yyreduce: break; case 71: -#line 622 "go.y" +#line 626 "go.y" { // normal test (yyval.node) = nod(OFOR, N, N); @@ -2979,7 +2983,7 @@ yyreduce: break; case 73: -#line 631 "go.y" +#line 635 "go.y" { (yyval.node) = (yyvsp[(1) - (2)].node); (yyval.node)->nbody = concat((yyval.node)->nbody, (yyvsp[(2) - (2)].list)); @@ -2987,14 +2991,14 @@ yyreduce: break; case 74: -#line 638 "go.y" +#line 642 "go.y" { markdcl(); } break; case 75: -#line 642 "go.y" +#line 646 "go.y" { (yyval.node) = (yyvsp[(3) - (3)].node); popdcl(); @@ -3002,7 +3006,7 @@ yyreduce: break; case 76: -#line 649 "go.y" +#line 653 "go.y" { // test (yyval.node) = nod(OIF, N, N); @@ -3011,7 +3015,7 @@ yyreduce: break; case 77: -#line 655 "go.y" +#line 659 "go.y" { // init ; test (yyval.node) = nod(OIF, N, N); @@ -3022,14 +3026,14 @@ yyreduce: break; case 78: -#line 666 "go.y" +#line 670 "go.y" { markdcl(); } break; case 79: -#line 670 "go.y" +#line 674 "go.y" { if((yyvsp[(3) - (3)].node)->ntest == N) yyerror("missing condition in if statement"); @@ -3037,14 +3041,14 @@ yyreduce: break; case 80: -#line 675 "go.y" +#line 679 "go.y" { (yyvsp[(3) - (5)].node)->nbody = (yyvsp[(5) - (5)].list); } break; case 81: -#line 679 "go.y" +#line 683 "go.y" { Node *n; NodeList *nn; @@ -3062,14 +3066,14 @@ yyreduce: break; case 82: -#line 696 "go.y" +#line 700 "go.y" { markdcl(); } break; case 83: -#line 700 "go.y" +#line 704 "go.y" { if((yyvsp[(4) - (5)].node)->ntest == N) yyerror("missing condition in if statement"); @@ -3079,28 +3083,28 @@ yyreduce: break; case 84: -#line 708 "go.y" +#line 712 "go.y" { (yyval.list) = nil; } break; case 85: -#line 712 "go.y" +#line 716 "go.y" { (yyval.list) = concat((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].list)); } break; case 86: -#line 717 "go.y" +#line 721 "go.y" { (yyval.list) = nil; } break; case 87: -#line 721 "go.y" +#line 725 "go.y" { NodeList *node; @@ -3112,14 +3116,14 @@ yyreduce: break; case 88: -#line 732 "go.y" +#line 736 "go.y" { markdcl(); } break; case 89: -#line 736 "go.y" +#line 740 "go.y" { Node *n; n = (yyvsp[(3) - (3)].node)->ntest; @@ -3130,7 +3134,7 @@ yyreduce: break; case 90: -#line 744 "go.y" +#line 748 "go.y" { (yyval.node) = (yyvsp[(3) - (7)].node); (yyval.node)->op = OSWITCH; @@ -3141,14 +3145,14 @@ yyreduce: break; case 91: -#line 754 "go.y" +#line 758 "go.y" { typesw = nod(OXXX, typesw, N); } break; case 92: -#line 758 "go.y" +#line 762 "go.y" { (yyval.node) = nod(OSELECT, N, N); (yyval.node)->lineno = typesw->lineno; @@ -3158,154 +3162,154 @@ yyreduce: break; case 94: -#line 771 "go.y" +#line 775 "go.y" { (yyval.node) = nod(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 95: -#line 775 "go.y" +#line 779 "go.y" { (yyval.node) = nod(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 96: -#line 779 "go.y" +#line 783 "go.y" { (yyval.node) = nod(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 97: -#line 783 "go.y" +#line 787 "go.y" { (yyval.node) = nod(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 98: -#line 787 "go.y" +#line 791 "go.y" { (yyval.node) = nod(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 99: -#line 791 "go.y" +#line 795 "go.y" { (yyval.node) = nod(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 100: -#line 795 "go.y" +#line 799 "go.y" { (yyval.node) = nod(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 101: -#line 799 "go.y" +#line 803 "go.y" { (yyval.node) = nod(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 102: -#line 803 "go.y" +#line 807 "go.y" { (yyval.node) = nod(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 103: -#line 807 "go.y" +#line 811 "go.y" { (yyval.node) = nod(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 104: -#line 811 "go.y" +#line 815 "go.y" { (yyval.node) = nod(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 105: -#line 815 "go.y" +#line 819 "go.y" { (yyval.node) = nod(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 106: -#line 819 "go.y" +#line 823 "go.y" { (yyval.node) = nod(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 107: -#line 823 "go.y" +#line 827 "go.y" { (yyval.node) = nod(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 108: -#line 827 "go.y" +#line 831 "go.y" { (yyval.node) = nod(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 109: -#line 831 "go.y" +#line 835 "go.y" { (yyval.node) = nod(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 110: -#line 835 "go.y" +#line 839 "go.y" { (yyval.node) = nod(OANDNOT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 111: -#line 839 "go.y" +#line 843 "go.y" { (yyval.node) = nod(OLSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 112: -#line 843 "go.y" +#line 847 "go.y" { (yyval.node) = nod(ORSH, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 113: -#line 848 "go.y" +#line 852 "go.y" { (yyval.node) = nod(OSEND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 115: -#line 855 "go.y" +#line 859 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; case 116: -#line 859 "go.y" +#line 863 "go.y" { if((yyvsp[(2) - (2)].node)->op == OCOMPLIT) { // Special case for &T{...}: turn into (*T){...}. @@ -3319,28 +3323,28 @@ yyreduce: break; case 117: -#line 870 "go.y" +#line 874 "go.y" { (yyval.node) = nod(OPLUS, (yyvsp[(2) - (2)].node), N); } break; case 118: -#line 874 "go.y" +#line 878 "go.y" { (yyval.node) = nod(OMINUS, (yyvsp[(2) - (2)].node), N); } break; case 119: -#line 878 "go.y" +#line 882 "go.y" { (yyval.node) = nod(ONOT, (yyvsp[(2) - (2)].node), N); } break; case 120: -#line 882 "go.y" +#line 886 "go.y" { yyerror("the bitwise complement operator is ^"); (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N); @@ -3348,28 +3352,28 @@ yyreduce: break; case 121: -#line 887 "go.y" +#line 891 "go.y" { (yyval.node) = nod(OCOM, (yyvsp[(2) - (2)].node), N); } break; case 122: -#line 891 "go.y" +#line 895 "go.y" { (yyval.node) = nod(ORECV, (yyvsp[(2) - (2)].node), N); } break; case 123: -#line 901 "go.y" +#line 905 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (3)].node), N); } break; case 124: -#line 905 "go.y" +#line 909 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N); (yyval.node)->list = (yyvsp[(3) - (5)].list); @@ -3377,7 +3381,7 @@ yyreduce: break; case 125: -#line 910 "go.y" +#line 914 "go.y" { (yyval.node) = nod(OCALL, (yyvsp[(1) - (6)].node), N); (yyval.node)->list = (yyvsp[(3) - (6)].list); @@ -3386,14 +3390,14 @@ yyreduce: break; case 126: -#line 918 "go.y" +#line 922 "go.y" { (yyval.node) = nodlit((yyvsp[(1) - (1)].val)); } break; case 128: -#line 923 "go.y" +#line 927 "go.y" { if((yyvsp[(1) - (3)].node)->op == OPACK) { Sym *s; @@ -3407,35 +3411,35 @@ yyreduce: break; case 129: -#line 934 "go.y" +#line 938 "go.y" { (yyval.node) = nod(ODOTTYPE, (yyvsp[(1) - (5)].node), (yyvsp[(4) - (5)].node)); } break; case 130: -#line 938 "go.y" +#line 942 "go.y" { (yyval.node) = nod(OTYPESW, N, (yyvsp[(1) - (5)].node)); } break; case 131: -#line 942 "go.y" +#line 946 "go.y" { (yyval.node) = nod(OINDEX, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)); } break; case 132: -#line 946 "go.y" +#line 950 "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 955 "go.y" { // conversion (yyval.node) = nod(OCALL, (yyvsp[(1) - (5)].node), N); @@ -3444,7 +3448,7 @@ yyreduce: break; case 135: -#line 957 "go.y" +#line 961 "go.y" { (yyval.node) = (yyvsp[(3) - (5)].node); (yyval.node)->right = (yyvsp[(1) - (5)].node); @@ -3454,7 +3458,7 @@ yyreduce: break; case 136: -#line 964 "go.y" +#line 968 "go.y" { (yyval.node) = (yyvsp[(3) - (5)].node); (yyval.node)->right = (yyvsp[(1) - (5)].node); @@ -3463,7 +3467,7 @@ yyreduce: break; case 137: -#line 970 "go.y" +#line 974 "go.y" { yyerror("cannot parenthesize type in composite literal"); (yyval.node) = (yyvsp[(5) - (7)].node); @@ -3473,7 +3477,7 @@ yyreduce: break; case 139: -#line 979 "go.y" +#line 983 "go.y" { // composite expression. // make node early so we get the right line number. @@ -3482,14 +3486,14 @@ yyreduce: break; case 140: -#line 987 "go.y" +#line 991 "go.y" { (yyval.node) = nod(OKEY, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); } break; case 141: -#line 993 "go.y" +#line 997 "go.y" { // These nodes do not carry line numbers. // Since a composite literal commonly spans several lines, @@ -3509,7 +3513,7 @@ yyreduce: break; case 142: -#line 1010 "go.y" +#line 1014 "go.y" { (yyval.node) = (yyvsp[(2) - (4)].node); (yyval.node)->list = (yyvsp[(3) - (4)].list); @@ -3517,7 +3521,7 @@ yyreduce: break; case 144: -#line 1018 "go.y" +#line 1022 "go.y" { (yyval.node) = (yyvsp[(2) - (4)].node); (yyval.node)->list = (yyvsp[(3) - (4)].list); @@ -3525,7 +3529,7 @@ yyreduce: break; case 146: -#line 1026 "go.y" +#line 1030 "go.y" { (yyval.node) = (yyvsp[(2) - (3)].node); @@ -3545,21 +3549,21 @@ yyreduce: break; case 150: -#line 1052 "go.y" +#line 1056 "go.y" { (yyval.i) = LBODY; } break; case 151: -#line 1056 "go.y" +#line 1060 "go.y" { (yyval.i) = '{'; } break; case 152: -#line 1067 "go.y" +#line 1071 "go.y" { if((yyvsp[(1) - (1)].sym) == S) (yyval.node) = N; @@ -3569,21 +3573,21 @@ yyreduce: break; case 153: -#line 1076 "go.y" +#line 1080 "go.y" { (yyval.node) = dclname((yyvsp[(1) - (1)].sym)); } break; case 154: -#line 1081 "go.y" +#line 1085 "go.y" { (yyval.node) = N; } break; case 156: -#line 1088 "go.y" +#line 1092 "go.y" { (yyval.sym) = (yyvsp[(1) - (1)].sym); // during imports, unqualified non-exported identifiers are from builtinpkg @@ -3593,14 +3597,14 @@ yyreduce: break; case 158: -#line 1096 "go.y" +#line 1100 "go.y" { (yyval.sym) = S; } break; case 159: -#line 1102 "go.y" +#line 1106 "go.y" { Pkg *p; @@ -3616,7 +3620,7 @@ yyreduce: break; case 160: -#line 1117 "go.y" +#line 1121 "go.y" { (yyval.node) = oldname((yyvsp[(1) - (1)].sym)); if((yyval.node)->pack != N) @@ -3625,7 +3629,7 @@ yyreduce: break; case 162: -#line 1137 "go.y" +#line 1141 "go.y" { yyerror("final argument in variadic function missing type"); (yyval.node) = nod(ODDD, typenod(typ(TINTER)), N); @@ -3633,35 +3637,35 @@ yyreduce: break; case 163: -#line 1142 "go.y" +#line 1146 "go.y" { (yyval.node) = nod(ODDD, (yyvsp[(2) - (2)].node), N); } break; case 169: -#line 1153 "go.y" +#line 1157 "go.y" { (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N); } break; case 173: -#line 1162 "go.y" +#line 1166 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; case 178: -#line 1172 "go.y" +#line 1176 "go.y" { (yyval.node) = nod(OTPAREN, (yyvsp[(2) - (3)].node), N); } break; case 188: -#line 1193 "go.y" +#line 1197 "go.y" { if((yyvsp[(1) - (3)].node)->op == OPACK) { Sym *s; @@ -3675,14 +3679,14 @@ yyreduce: break; case 189: -#line 1206 "go.y" +#line 1210 "go.y" { (yyval.node) = nod(OTARRAY, (yyvsp[(2) - (4)].node), (yyvsp[(4) - (4)].node)); } break; case 190: -#line 1210 "go.y" +#line 1214 "go.y" { // array literal of nelem (yyval.node) = nod(OTARRAY, nod(ODDD, N, N), (yyvsp[(4) - (4)].node)); @@ -3690,7 +3694,7 @@ yyreduce: break; case 191: -#line 1215 "go.y" +#line 1219 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(2) - (2)].node), N); (yyval.node)->etype = Cboth; @@ -3698,7 +3702,7 @@ yyreduce: break; case 192: -#line 1220 "go.y" +#line 1224 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N); (yyval.node)->etype = Csend; @@ -3706,21 +3710,21 @@ yyreduce: break; case 193: -#line 1225 "go.y" +#line 1229 "go.y" { (yyval.node) = nod(OTMAP, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)); } break; case 196: -#line 1233 "go.y" +#line 1237 "go.y" { (yyval.node) = nod(OIND, (yyvsp[(2) - (2)].node), N); } break; case 197: -#line 1239 "go.y" +#line 1243 "go.y" { (yyval.node) = nod(OTCHAN, (yyvsp[(3) - (3)].node), N); (yyval.node)->etype = Crecv; @@ -3728,7 +3732,7 @@ yyreduce: break; case 198: -#line 1246 "go.y" +#line 1250 "go.y" { (yyval.node) = nod(OTSTRUCT, N, N); (yyval.node)->list = (yyvsp[(3) - (5)].list); @@ -3737,7 +3741,7 @@ yyreduce: break; case 199: -#line 1252 "go.y" +#line 1256 "go.y" { (yyval.node) = nod(OTSTRUCT, N, N); fixlbrace((yyvsp[(2) - (3)].i)); @@ -3745,7 +3749,7 @@ yyreduce: break; case 200: -#line 1259 "go.y" +#line 1263 "go.y" { (yyval.node) = nod(OTINTER, N, N); (yyval.node)->list = (yyvsp[(3) - (5)].list); @@ -3754,7 +3758,7 @@ yyreduce: break; case 201: -#line 1265 "go.y" +#line 1269 "go.y" { (yyval.node) = nod(OTINTER, N, N); fixlbrace((yyvsp[(2) - (3)].i)); @@ -3762,7 +3766,7 @@ yyreduce: break; case 202: -#line 1276 "go.y" +#line 1280 "go.y" { (yyval.node) = (yyvsp[(2) - (3)].node); if((yyval.node) == N) @@ -3777,7 +3781,7 @@ yyreduce: break; case 203: -#line 1290 "go.y" +#line 1294 "go.y" { Node *t; @@ -3809,7 +3813,7 @@ yyreduce: break; case 204: -#line 1319 "go.y" +#line 1323 "go.y" { Node *rcvr, *t; @@ -3850,7 +3854,7 @@ yyreduce: break; case 205: -#line 1359 "go.y" +#line 1363 "go.y" { Sym *s; Type *t; @@ -3878,7 +3882,7 @@ yyreduce: break; case 206: -#line 1384 "go.y" +#line 1388 "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 +3901,7 @@ yyreduce: break; case 207: -#line 1402 "go.y" +#line 1406 "go.y" { (yyvsp[(3) - (5)].list) = checkarglist((yyvsp[(3) - (5)].list), 1); (yyval.node) = nod(OTFUNC, N, N); @@ -3907,14 +3911,14 @@ yyreduce: break; case 208: -#line 1410 "go.y" +#line 1414 "go.y" { (yyval.list) = nil; } break; case 209: -#line 1414 "go.y" +#line 1418 "go.y" { (yyval.list) = (yyvsp[(2) - (3)].list); if((yyval.list) == nil) @@ -3923,21 +3927,21 @@ yyreduce: break; case 210: -#line 1422 "go.y" +#line 1426 "go.y" { (yyval.list) = nil; } break; case 211: -#line 1426 "go.y" +#line 1430 "go.y" { (yyval.list) = list1(nod(ODCLFIELD, N, (yyvsp[(1) - (1)].node))); } break; case 212: -#line 1430 "go.y" +#line 1434 "go.y" { (yyvsp[(2) - (3)].list) = checkarglist((yyvsp[(2) - (3)].list), 0); (yyval.list) = (yyvsp[(2) - (3)].list); @@ -3945,14 +3949,14 @@ yyreduce: break; case 213: -#line 1437 "go.y" +#line 1441 "go.y" { closurehdr((yyvsp[(1) - (1)].node)); } break; case 214: -#line 1443 "go.y" +#line 1447 "go.y" { (yyval.node) = closurebody((yyvsp[(3) - (4)].list)); fixlbrace((yyvsp[(2) - (4)].i)); @@ -3960,21 +3964,21 @@ yyreduce: break; case 215: -#line 1448 "go.y" +#line 1452 "go.y" { (yyval.node) = closurebody(nil); } break; case 216: -#line 1459 "go.y" +#line 1463 "go.y" { (yyval.list) = nil; } break; case 217: -#line 1463 "go.y" +#line 1467 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(2) - (3)].list)); if(nsyntaxerrors == 0) @@ -3985,56 +3989,56 @@ yyreduce: break; case 219: -#line 1474 "go.y" +#line 1478 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; case 221: -#line 1481 "go.y" +#line 1485 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; case 222: -#line 1487 "go.y" +#line 1491 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 223: -#line 1491 "go.y" +#line 1495 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 225: -#line 1498 "go.y" +#line 1502 "go.y" { (yyval.list) = concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); } break; case 226: -#line 1504 "go.y" +#line 1508 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 227: -#line 1508 "go.y" +#line 1512 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 228: -#line 1514 "go.y" +#line 1518 "go.y" { NodeList *l; @@ -4060,7 +4064,7 @@ yyreduce: break; case 229: -#line 1537 "go.y" +#line 1541 "go.y" { (yyvsp[(1) - (2)].node)->val = (yyvsp[(2) - (2)].val); (yyval.list) = list1((yyvsp[(1) - (2)].node)); @@ -4068,7 +4072,7 @@ yyreduce: break; case 230: -#line 1542 "go.y" +#line 1546 "go.y" { (yyvsp[(2) - (4)].node)->val = (yyvsp[(4) - (4)].val); (yyval.list) = list1((yyvsp[(2) - (4)].node)); @@ -4077,7 +4081,7 @@ yyreduce: break; case 231: -#line 1548 "go.y" +#line 1552 "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 +4090,7 @@ yyreduce: break; case 232: -#line 1554 "go.y" +#line 1558 "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 +4100,7 @@ yyreduce: break; case 233: -#line 1561 "go.y" +#line 1565 "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 +4110,7 @@ yyreduce: break; case 234: -#line 1570 "go.y" +#line 1574 "go.y" { Node *n; @@ -4118,7 +4122,7 @@ yyreduce: break; case 235: -#line 1579 "go.y" +#line 1583 "go.y" { Pkg *pkg; @@ -4134,14 +4138,14 @@ yyreduce: break; case 236: -#line 1594 "go.y" +#line 1598 "go.y" { (yyval.node) = embedded((yyvsp[(1) - (1)].sym)); } break; case 237: -#line 1600 "go.y" +#line 1604 "go.y" { (yyval.node) = nod(ODCLFIELD, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); ifacedcl((yyval.node)); @@ -4149,14 +4153,14 @@ yyreduce: break; case 238: -#line 1605 "go.y" +#line 1609 "go.y" { (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(1) - (1)].sym))); } break; case 239: -#line 1609 "go.y" +#line 1613 "go.y" { (yyval.node) = nod(ODCLFIELD, N, oldname((yyvsp[(2) - (3)].sym))); yyerror("cannot parenthesize embedded type"); @@ -4164,7 +4168,7 @@ yyreduce: break; case 240: -#line 1616 "go.y" +#line 1620 "go.y" { // without func keyword (yyvsp[(2) - (4)].list) = checkarglist((yyvsp[(2) - (4)].list), 1); @@ -4175,7 +4179,7 @@ yyreduce: break; case 242: -#line 1630 "go.y" +#line 1634 "go.y" { (yyval.node) = nod(ONONAME, N, N); (yyval.node)->sym = (yyvsp[(1) - (2)].sym); @@ -4184,7 +4188,7 @@ yyreduce: break; case 243: -#line 1636 "go.y" +#line 1640 "go.y" { (yyval.node) = nod(ONONAME, N, N); (yyval.node)->sym = (yyvsp[(1) - (2)].sym); @@ -4193,56 +4197,56 @@ yyreduce: break; case 245: -#line 1645 "go.y" +#line 1649 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 246: -#line 1649 "go.y" +#line 1653 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 247: -#line 1654 "go.y" +#line 1658 "go.y" { (yyval.list) = nil; } break; case 248: -#line 1658 "go.y" +#line 1662 "go.y" { (yyval.list) = (yyvsp[(1) - (2)].list); } break; case 249: -#line 1666 "go.y" +#line 1670 "go.y" { (yyval.node) = N; } break; case 251: -#line 1671 "go.y" +#line 1675 "go.y" { (yyval.node) = liststmt((yyvsp[(1) - (1)].list)); } break; case 253: -#line 1676 "go.y" +#line 1680 "go.y" { (yyval.node) = N; } break; case 259: -#line 1687 "go.y" +#line 1691 "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 +4254,7 @@ yyreduce: break; case 260: -#line 1692 "go.y" +#line 1696 "go.y" { NodeList *l; @@ -4263,7 +4267,7 @@ yyreduce: break; case 261: -#line 1702 "go.y" +#line 1706 "go.y" { // will be converted to OFALL (yyval.node) = nod(OXFALL, N, N); @@ -4271,35 +4275,35 @@ yyreduce: break; case 262: -#line 1707 "go.y" +#line 1711 "go.y" { (yyval.node) = nod(OBREAK, (yyvsp[(2) - (2)].node), N); } break; case 263: -#line 1711 "go.y" +#line 1715 "go.y" { (yyval.node) = nod(OCONTINUE, (yyvsp[(2) - (2)].node), N); } break; case 264: -#line 1715 "go.y" +#line 1719 "go.y" { (yyval.node) = nod(OPROC, (yyvsp[(2) - (2)].node), N); } break; case 265: -#line 1719 "go.y" +#line 1723 "go.y" { (yyval.node) = nod(ODEFER, (yyvsp[(2) - (2)].node), N); } break; case 266: -#line 1723 "go.y" +#line 1727 "go.y" { (yyval.node) = nod(OGOTO, (yyvsp[(2) - (2)].node), N); (yyval.node)->sym = dclstack; // context, for goto restrictions @@ -4307,7 +4311,7 @@ yyreduce: break; case 267: -#line 1728 "go.y" +#line 1732 "go.y" { (yyval.node) = nod(ORETURN, N, N); (yyval.node)->list = (yyvsp[(2) - (2)].list); @@ -4327,7 +4331,7 @@ yyreduce: break; case 268: -#line 1747 "go.y" +#line 1751 "go.y" { (yyval.list) = nil; if((yyvsp[(1) - (1)].node) != N) @@ -4336,7 +4340,7 @@ yyreduce: break; case 269: -#line 1753 "go.y" +#line 1757 "go.y" { (yyval.list) = (yyvsp[(1) - (3)].list); if((yyvsp[(3) - (3)].node) != N) @@ -4345,189 +4349,189 @@ yyreduce: break; case 270: -#line 1761 "go.y" +#line 1765 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 271: -#line 1765 "go.y" +#line 1769 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 272: -#line 1771 "go.y" +#line 1775 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 273: -#line 1775 "go.y" +#line 1779 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 274: -#line 1781 "go.y" +#line 1785 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 275: -#line 1785 "go.y" +#line 1789 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 276: -#line 1791 "go.y" +#line 1795 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 277: -#line 1795 "go.y" +#line 1799 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 278: -#line 1804 "go.y" +#line 1808 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 279: -#line 1808 "go.y" +#line 1812 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 280: -#line 1812 "go.y" +#line 1816 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 281: -#line 1816 "go.y" +#line 1820 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 282: -#line 1821 "go.y" +#line 1825 "go.y" { (yyval.list) = nil; } break; case 283: -#line 1825 "go.y" +#line 1829 "go.y" { (yyval.list) = (yyvsp[(1) - (2)].list); } break; case 288: -#line 1839 "go.y" +#line 1843 "go.y" { (yyval.node) = N; } break; case 290: -#line 1845 "go.y" +#line 1849 "go.y" { (yyval.list) = nil; } break; case 292: -#line 1851 "go.y" +#line 1855 "go.y" { (yyval.node) = N; } break; case 294: -#line 1857 "go.y" +#line 1861 "go.y" { (yyval.list) = nil; } break; case 296: -#line 1863 "go.y" +#line 1867 "go.y" { (yyval.list) = nil; } break; case 298: -#line 1869 "go.y" +#line 1873 "go.y" { (yyval.list) = nil; } break; case 300: -#line 1875 "go.y" +#line 1879 "go.y" { (yyval.val).ctype = CTxxx; } break; case 302: -#line 1885 "go.y" +#line 1889 "go.y" { importimport((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].val).u.sval); } break; case 303: -#line 1889 "go.y" +#line 1893 "go.y" { importvar((yyvsp[(2) - (4)].sym), (yyvsp[(3) - (4)].type)); } break; case 304: -#line 1893 "go.y" +#line 1897 "go.y" { importconst((yyvsp[(2) - (5)].sym), types[TIDEAL], (yyvsp[(4) - (5)].node)); } break; case 305: -#line 1897 "go.y" +#line 1901 "go.y" { importconst((yyvsp[(2) - (6)].sym), (yyvsp[(3) - (6)].type), (yyvsp[(5) - (6)].node)); } break; case 306: -#line 1901 "go.y" +#line 1905 "go.y" { importtype((yyvsp[(2) - (4)].type), (yyvsp[(3) - (4)].type)); } break; case 307: -#line 1905 "go.y" +#line 1909 "go.y" { if((yyvsp[(2) - (4)].node) == N) { dclcontext = PEXTERN; // since we skip the funcbody below @@ -4548,7 +4552,7 @@ yyreduce: break; case 308: -#line 1925 "go.y" +#line 1929 "go.y" { (yyval.sym) = (yyvsp[(1) - (1)].sym); structpkg = (yyval.sym)->pkg; @@ -4556,7 +4560,7 @@ yyreduce: break; case 309: -#line 1932 "go.y" +#line 1936 "go.y" { (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym)); importsym((yyvsp[(1) - (1)].sym), OTYPE); @@ -4564,14 +4568,14 @@ yyreduce: break; case 315: -#line 1952 "go.y" +#line 1956 "go.y" { (yyval.type) = pkgtype((yyvsp[(1) - (1)].sym)); } break; case 316: -#line 1956 "go.y" +#line 1960 "go.y" { // predefined name like uint8 (yyvsp[(1) - (1)].sym) = pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg); @@ -4584,49 +4588,49 @@ yyreduce: break; case 317: -#line 1966 "go.y" +#line 1970 "go.y" { (yyval.type) = aindex(N, (yyvsp[(3) - (3)].type)); } break; case 318: -#line 1970 "go.y" +#line 1974 "go.y" { (yyval.type) = aindex(nodlit((yyvsp[(2) - (4)].val)), (yyvsp[(4) - (4)].type)); } break; case 319: -#line 1974 "go.y" +#line 1978 "go.y" { (yyval.type) = maptype((yyvsp[(3) - (5)].type), (yyvsp[(5) - (5)].type)); } break; case 320: -#line 1978 "go.y" +#line 1982 "go.y" { (yyval.type) = tostruct((yyvsp[(3) - (4)].list)); } break; case 321: -#line 1982 "go.y" +#line 1986 "go.y" { (yyval.type) = tointerface((yyvsp[(3) - (4)].list)); } break; case 322: -#line 1986 "go.y" +#line 1990 "go.y" { (yyval.type) = ptrto((yyvsp[(2) - (2)].type)); } break; case 323: -#line 1990 "go.y" +#line 1994 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(2) - (2)].type); @@ -4635,7 +4639,7 @@ yyreduce: break; case 324: -#line 1996 "go.y" +#line 2000 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (4)].type); @@ -4644,7 +4648,7 @@ yyreduce: break; case 325: -#line 2002 "go.y" +#line 2006 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (3)].type); @@ -4653,7 +4657,7 @@ yyreduce: break; case 326: -#line 2010 "go.y" +#line 2014 "go.y" { (yyval.type) = typ(TCHAN); (yyval.type)->type = (yyvsp[(3) - (3)].type); @@ -4662,14 +4666,14 @@ yyreduce: break; case 327: -#line 2018 "go.y" +#line 2022 "go.y" { (yyval.type) = functype(nil, (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list)); } break; case 328: -#line 2024 "go.y" +#line 2028 "go.y" { (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(2) - (3)].type))); if((yyvsp[(1) - (3)].sym)) @@ -4679,7 +4683,7 @@ yyreduce: break; case 329: -#line 2031 "go.y" +#line 2035 "go.y" { Type *t; @@ -4696,7 +4700,7 @@ yyreduce: break; case 330: -#line 2047 "go.y" +#line 2051 "go.y" { Sym *s; @@ -4715,49 +4719,49 @@ yyreduce: break; case 331: -#line 2065 "go.y" +#line 2069 "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 2073 "go.y" { (yyval.node) = nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type))); } break; case 333: -#line 2074 "go.y" +#line 2078 "go.y" { (yyval.list) = nil; } break; case 335: -#line 2081 "go.y" +#line 2085 "go.y" { (yyval.list) = (yyvsp[(2) - (3)].list); } break; case 336: -#line 2085 "go.y" +#line 2089 "go.y" { (yyval.list) = list1(nod(ODCLFIELD, N, typenod((yyvsp[(1) - (1)].type)))); } break; case 337: -#line 2095 "go.y" +#line 2099 "go.y" { (yyval.node) = nodlit((yyvsp[(1) - (1)].val)); } break; case 338: -#line 2099 "go.y" +#line 2103 "go.y" { (yyval.node) = nodlit((yyvsp[(2) - (2)].val)); switch((yyval.node)->val.ctype){ @@ -4775,7 +4779,7 @@ yyreduce: break; case 339: -#line 2114 "go.y" +#line 2118 "go.y" { (yyval.node) = oldname(pkglookup((yyvsp[(1) - (1)].sym)->name, builtinpkg)); if((yyval.node)->op != OLITERAL) @@ -4784,7 +4788,7 @@ yyreduce: break; case 341: -#line 2123 "go.y" +#line 2127 "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 +4802,42 @@ yyreduce: break; case 344: -#line 2139 "go.y" +#line 2143 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 345: -#line 2143 "go.y" +#line 2147 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 346: -#line 2149 "go.y" +#line 2153 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 347: -#line 2153 "go.y" +#line 2157 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } break; case 348: -#line 2159 "go.y" +#line 2163 "go.y" { (yyval.list) = list1((yyvsp[(1) - (1)].node)); } break; case 349: -#line 2163 "go.y" +#line 2167 "go.y" { (yyval.list) = list((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); } @@ -4841,7 +4845,7 @@ yyreduce: /* Line 1267 of yacc.c. */ -#line 4846 "y.tab.c" +#line 4850 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -5055,7 +5059,7 @@ yyreturn: } -#line 2167 "go.y" +#line 2171 "go.y" static void |