summaryrefslogtreecommitdiff
path: root/src/cmd/gc/dcl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/dcl.c')
-rw-r--r--src/cmd/gc/dcl.c136
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;
+}