diff options
Diffstat (limited to 'src/cmd/gc/dcl.c')
-rw-r--r-- | src/cmd/gc/dcl.c | 136 |
1 files changed, 106 insertions, 30 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 32f334b71..aa2489d9a 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -150,16 +150,35 @@ testdclstack(void) void redeclare(Sym *s, char *where) { - if(s->lastlineno == 0) - yyerror("%S redeclared %s\n" - "\tprevious declaration during import", - s, where); - else + Strlit *pkgstr; + int line1, line2; + + if(s->lastlineno == 0) { + pkgstr = s->origpkg ? s->origpkg->path : s->pkg->path; yyerror("%S redeclared %s\n" + "\tprevious declaration during import \"%Z\"", + s, where, pkgstr); + } else { + line1 = parserline(); + line2 = s->lastlineno; + + // When an import and a declaration collide in separate files, + // present the import as the "redeclared", because the declaration + // is visible where the import is, but not vice versa. + // See issue 4510. + if(s->def == N) { + line2 = line1; + line1 = s->lastlineno; + } + + yyerrorl(line1, "%S redeclared %s\n" "\tprevious declaration at %L", - s, where, s->lastlineno); + s, where, line2); + } } +static int vargen; + /* * declare individual names - var, typ, const */ @@ -168,7 +187,10 @@ declare(Node *n, int ctxt) { Sym *s; int gen; - static int typegen, vargen; + static int typegen; + + if(ctxt == PDISCARD) + return; if(isblank(n)) return; @@ -180,6 +202,9 @@ declare(Node *n, int ctxt) if(importpkg == nil && !typecheckok && s->pkg != localpkg) yyerror("cannot declare name %S", s); + if(ctxt == PEXTERN && strcmp(s->name, "init") == 0) + yyerror("cannot declare init - must be func", s); + gen = 0; if(ctxt == PEXTERN) { externdcl = list(externdcl, n); @@ -192,7 +217,7 @@ declare(Node *n, int ctxt) curfn->dcl = list(curfn->dcl, n); if(n->op == OTYPE) gen = ++typegen; - else if(n->op == ONAME) + else if(n->op == ONAME && ctxt == PAUTO && strstr(s->name, "·") == nil) gen = ++vargen; pushdcl(s); n->curfn = curfn; @@ -237,7 +262,7 @@ variter(NodeList *vl, Node *t, NodeList *el) init = nil; doexpr = el != nil; - + if(count(el) == 1 && count(vl) > 1) { e = el->n; as2 = nod(OAS2, N, N); @@ -464,7 +489,7 @@ colasdefn(NodeList *left, Node *defn) if(isblank(n)) continue; if(!colasname(n)) { - yyerror("non-name %N on left side of :=", n); + yyerrorl(defn->lineno, "non-name %N on left side of :=", n); nerr++; continue; } @@ -479,11 +504,11 @@ colasdefn(NodeList *left, Node *defn) l->n = n; } if(nnew == 0 && nerr == 0) - yyerror("no new variables on left side of :="); + yyerrorl(defn->lineno, "no new variables on left side of :="); } Node* -colas(NodeList *left, NodeList *right) +colas(NodeList *left, NodeList *right, int32 lno) { Node *as; @@ -491,6 +516,7 @@ colas(NodeList *left, NodeList *right) as->list = left; as->rlist = right; as->colas = 1; + as->lineno = lno; colasdefn(left, as); // make the tree prettier; not necessary @@ -515,7 +541,7 @@ ifacedcl(Node *n) if(n->op != ODCLFIELD || n->right == N) fatal("ifacedcl"); - dclcontext = PAUTO; + dclcontext = PPARAM; markdcl(); funcdepth++; n->outer = curfn; @@ -526,6 +552,7 @@ ifacedcl(Node *n) // seen the body of a function but since an interface // field declaration does not have a body, we must // call it now to pop the current declaration context. + dclcontext = PAUTO; funcbody(n); } @@ -567,6 +594,11 @@ funcargs(Node *nt) if(nt->op != OTFUNC) fatal("funcargs %O", nt->op); + // re-start the variable generation number + // we want to use small numbers for the return variables, + // so let them have the chunk starting at 1. + vargen = count(nt->rlist); + // declare the receiver and in arguments. // no n->defn because type checking of func header // will not fill in the types until later @@ -578,6 +610,8 @@ funcargs(Node *nt) n->left->op = ONAME; n->left->ntype = n->right; declare(n->left, PPARAM); + if(dclcontext == PAUTO) + n->left->vargen = ++vargen; } } for(l=nt->list; l; l=l->next) { @@ -588,29 +622,44 @@ funcargs(Node *nt) n->left->op = ONAME; n->left->ntype = n->right; declare(n->left, PPARAM); + if(dclcontext == PAUTO) + n->left->vargen = ++vargen; } } // declare the out arguments. - gen = 0; + gen = count(nt->list); + int i = 0; for(l=nt->rlist; l; l=l->next) { n = l->n; + if(n->op != ODCLFIELD) fatal("funcargs out %O", n->op); - if(n->left != N) { - n->left->op = ONAME; - n->left->ntype = n->right; - if(isblank(n->left)) { - // Give it a name so we can assign to it during return. - // preserve the original in ->orig - nn = nod(OXXX, N, N); - *nn = *n->left; - n->left = nn; - snprint(namebuf, sizeof(namebuf), ".anon%d", gen++); - n->left->sym = lookup(namebuf); - } - declare(n->left, PPARAMOUT); + + if(n->left == N) { + // give it a name so escape analysis has nodes to work with + snprint(namebuf, sizeof(namebuf), "~anon%d", gen++); + n->left = newname(lookup(namebuf)); + // TODO: n->left->missing = 1; + } + + n->left->op = ONAME; + + if(isblank(n->left)) { + // Give it a name so we can assign to it during return. + // preserve the original in ->orig + nn = nod(OXXX, N, N); + *nn = *n->left; + n->left = nn; + + snprint(namebuf, sizeof(namebuf), "~anon%d", gen++); + n->left->sym = lookup(namebuf); } + + n->left->ntype = n->right; + declare(n->left, PPARAMOUT); + if(dclcontext == PAUTO) + n->left->vargen = ++i; } } @@ -978,8 +1027,11 @@ embedded(Sym *s) *utfrune(name, CenterDot) = 0; } - if(exportname(name) || s->pkg == builtinpkg) // old behaviour, tests pass, but is it correct? + if(exportname(name)) n = newname(lookup(name)); + else if(s->pkg == builtinpkg && importpkg != nil) + // The name of embedded builtins during imports belongs to importpkg. + n = newname(pkglookup(name, importpkg)); else n = newname(pkglookup(name, s->pkg)); n = nod(ODCLFIELD, n, oldname(s)); @@ -1124,6 +1176,7 @@ functype(Node *this, NodeList *in, NodeList *out) { Type *t; NodeList *rcvr; + Sym *s; t = typ(TFUNC); @@ -1141,7 +1194,12 @@ functype(Node *this, NodeList *in, NodeList *out) t->thistuple = 1; t->outtuple = count(out); t->intuple = count(in); - t->outnamed = t->outtuple > 0 && out->n->left != N; + t->outnamed = 0; + if(t->outtuple > 0 && out->n->left != N && out->n->left->orig != N) { + s = out->n->left->orig->sym; + if(s != S && s->name[0] != '~') + t->outnamed = 1; + } return t; } @@ -1249,7 +1307,7 @@ methodname1(Node *n, Node *t) * n is fieldname, pa is base type, t is function type */ void -addmethod(Sym *sf, Type *t, int local) +addmethod(Sym *sf, Type *t, int local, int nointerface) { Type *f, *d, *pa; Node *n; @@ -1332,6 +1390,7 @@ addmethod(Sym *sf, Type *t, int local) } f = structfield(n); + f->nointerface = nointerface; // during import unexported method names should be in the type's package if(importpkg && f->sym && !exportname(f->sym->name) && f->sym->pkg != structpkg) @@ -1382,3 +1441,20 @@ funccompile(Node *n, int isclosure) funcdepth = 0; dclcontext = PEXTERN; } + +Sym* +funcsym(Sym *s) +{ + char *p; + Sym *s1; + + p = smprint("%s·f", s->name); + s1 = pkglookup(p, s->pkg); + free(p); + if(s1->def == N) { + s1->def = newname(s1); + s1->def->shortname = newname(s); + funcsyms = list(funcsyms, s1->def); + } + return s1; +} |