summaryrefslogtreecommitdiff
path: root/src/cmd/gc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc')
-rw-r--r--src/cmd/gc/Makefile2
-rw-r--r--src/cmd/gc/dcl.c35
-rw-r--r--src/cmd/gc/doc.go2
-rw-r--r--src/cmd/gc/go.h4
-rw-r--r--src/cmd/gc/inl.c2
-rw-r--r--src/cmd/gc/lex.c2
-rw-r--r--src/cmd/gc/obj.c32
-rw-r--r--src/cmd/gc/reflect.c6
-rw-r--r--src/cmd/gc/runtime.go2
-rw-r--r--src/cmd/gc/subr.c28
-rw-r--r--src/cmd/gc/typecheck.c62
-rw-r--r--src/cmd/gc/walk.c14
12 files changed, 139 insertions, 52 deletions
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index df34c05b2..58e25faaf 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -6,7 +6,7 @@ include ../../Make.dist
install: y.tab.h builtin.c
-y.tab.h: go.y
+y.tab.h: go.y go.errors bisonerrors
bison -v -y -d go.y
# make yystate global, yytname mutable
cat y.tab.c | sed '/ int yystate;/d; s/int yychar;/int yychar, yystate;/; s/static const char \*const yytname/const char *yytname/; s/char const \*yymsgp/char *yymsgp/' >y1.tab.c
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 4a0e7430a..4121a45ab 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1168,21 +1168,22 @@ methodsym(Sym *nsym, Type *t0, int iface)
char *p;
Type *t;
char *suffix;
+ Pkg *spkg;
+ static Pkg *toppkg;
t = t0;
if(t == T)
goto bad;
s = t->sym;
- if(s == S) {
- if(!isptr[t->etype])
- goto bad;
+ if(s == S && isptr[t->etype]) {
t = t->type;
if(t == T)
goto bad;
s = t->sym;
- if(s == S)
- goto bad;
}
+ spkg = nil;
+ if(s != S)
+ spkg = s->pkg;
// if t0 == *t and t0 has a sym,
// we want to see *t, not t0, in the method name.
@@ -1195,11 +1196,23 @@ methodsym(Sym *nsym, Type *t0, int iface)
if(t0->width < types[tptr]->width)
suffix = "·i";
}
- if(t0->sym == S && isptr[t0->etype])
- p = smprint("(%-hT).%s%s", t0, nsym->name, suffix);
- else
- p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
- s = pkglookup(p, s->pkg);
+ if((spkg == nil || nsym->pkg != spkg) && !exportname(nsym->name)) {
+ if(t0->sym == S && isptr[t0->etype])
+ p = smprint("(%-hT).%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
+ else
+ p = smprint("%-hT.%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
+ } else {
+ if(t0->sym == S && isptr[t0->etype])
+ p = smprint("(%-hT).%s%s", t0, nsym->name, suffix);
+ else
+ p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
+ }
+ if(spkg == nil) {
+ if(toppkg == nil)
+ toppkg = mkpkg(strlit("go"));
+ spkg = toppkg;
+ }
+ s = pkglookup(p, spkg);
free(p);
return s;
@@ -1268,7 +1281,7 @@ addmethod(Sym *sf, Type *t, int local)
}
pa = pa->type;
- f = methtype(pa);
+ f = methtype(pa, 1);
if(f == T) {
t = pa;
if(t != T) {
diff --git a/src/cmd/gc/doc.go b/src/cmd/gc/doc.go
index 5a2977eab..163d3862c 100644
--- a/src/cmd/gc/doc.go
+++ b/src/cmd/gc/doc.go
@@ -26,7 +26,7 @@ package P to read the files of P's dependencies, only the compiled output
of P.
Usage:
- 6g [flags] file...
+ go tool 6g [flags] file...
The specified files must be Go source files and all part of the same package.
Substitute 6g with 8g or 5g where appropriate.
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 753360e46..8c4fff15a 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -1154,7 +1154,7 @@ int cplxsubtype(int et);
int eqtype(Type *t1, Type *t2);
int eqtypenoname(Type *t1, Type *t2);
void errorexit(void);
-void expandmeth(Sym *s, Type *t);
+void expandmeth(Type *t);
void fatal(char *fmt, ...);
void flusherrors(void);
void frame(int context);
@@ -1192,7 +1192,7 @@ NodeList* listtreecopy(NodeList *l);
Sym* lookup(char *name);
void* mal(int32 n);
Type* maptype(Type *key, Type *val);
-Type* methtype(Type *t);
+Type* methtype(Type *t, int mustname);
Pkg* mkpkg(Strlit *path);
Sym* ngotype(Node *n);
int noconv(Type *t1, Type *t2);
diff --git a/src/cmd/gc/inl.c b/src/cmd/gc/inl.c
index 96080cbfa..efce56057 100644
--- a/src/cmd/gc/inl.c
+++ b/src/cmd/gc/inl.c
@@ -182,6 +182,8 @@ ishairy(Node *n, int *budget)
case OCALLFUNC:
case OCALLINTER:
case OCALLMETH:
+ case OPANIC:
+ case ORECOVER:
if(debug['l'] < 4)
return 1;
break;
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 96786b5e6..e71fd3848 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -514,7 +514,7 @@ addidir(char* dir)
static int
islocalname(Strlit *name)
{
- if(!windows && name->len >= 1 && name->s[0] == '/')
+ if(name->len >= 1 && name->s[0] == '/')
return 1;
if(windows && name->len >= 3 &&
yy_isalpha(name->s[0]) && name->s[1] == ':' && name->s[2] == '/')
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index aae566dbb..e45b4e0d4 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -126,10 +126,37 @@ outhist(Biobuf *b)
{
Hist *h;
char *p, ds[] = {'c', ':', '/', 0};
+ char *tofree;
+ int n;
+ static int first = 1;
+ static char *goroot, *goroot_final;
+ if(first) {
+ // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
+ first = 0;
+ goroot = getenv("GOROOT");
+ goroot_final = getenv("GOROOT_FINAL");
+ if(goroot == nil)
+ goroot = "";
+ if(goroot_final == nil)
+ goroot_final = goroot;
+ if(strcmp(goroot, goroot_final) == 0) {
+ goroot = nil;
+ goroot_final = nil;
+ }
+ }
+
+ tofree = nil;
for(h = hist; h != H; h = h->link) {
p = h->name;
if(p) {
+ if(goroot != nil) {
+ n = strlen(goroot);
+ if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
+ tofree = smprint("%s%s", goroot_final, p+n);
+ p = tofree;
+ }
+ }
if(windows) {
// if windows variable is set, then, we know already,
// pathname is started with windows drive specifier
@@ -161,9 +188,12 @@ outhist(Biobuf *b)
outzfile(b, p);
}
}
-
}
zhist(b, h->line, h->offset);
+ if(tofree) {
+ free(tofree);
+ tofree = nil;
+ }
}
}
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index 0847e9a3f..07b426508 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -144,11 +144,11 @@ methods(Type *t)
Sig *a, *b;
Sym *method;
- // named method type
- mt = methtype(t);
+ // method type
+ mt = methtype(t, 0);
if(mt == T)
return nil;
- expandmeth(mt->sym, mt);
+ expandmeth(mt);
// type stored in interface word
it = t;
diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go
index 000b2328f..15a61d9ef 100644
--- a/src/cmd/gc/runtime.go
+++ b/src/cmd/gc/runtime.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// NOTE: If you change this file you must run "./mkbuiltin"
-// to update builtin.c.boot. This is not done automatically
+// to update builtin.c. This is not done automatically
// to avoid depending on having a working compiler binary.
// +build ignore
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index 6eb7734f0..681c023a0 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -944,7 +944,7 @@ isideal(Type *t)
* return type to hang methods off (r).
*/
Type*
-methtype(Type *t)
+methtype(Type *t, int mustname)
{
if(t == T)
return T;
@@ -959,7 +959,7 @@ methtype(Type *t)
}
// need a type name
- if(t->sym == S)
+ if(t->sym == S && (mustname || t->etype != TSTRUCT))
return T;
// check types
@@ -2101,7 +2101,7 @@ lookdot0(Sym *s, Type *t, Type **save, int ignorecase)
c++;
}
}
- u = methtype(t);
+ u = methtype(t, 0);
if(u != T) {
for(f=u->method; f!=T; f=f->down)
if(f->embedded == 0 && (f->sym == s || (ignorecase && ucistrcmp(f->sym->name, s->name) == 0))) {
@@ -2251,7 +2251,7 @@ expand0(Type *t, int followptr)
return;
}
- u = methtype(t);
+ u = methtype(t, 0);
if(u != T) {
for(f=u->method; f!=T; f=f->down) {
if(f->sym->flags & SymUniq)
@@ -2301,14 +2301,12 @@ out:
}
void
-expandmeth(Sym *s, Type *t)
+expandmeth(Type *t)
{
Symlink *sl;
Type *f;
int c, d;
- if(s == S)
- return;
if(t == T || t->xmethod != nil)
return;
@@ -3021,9 +3019,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
return 1;
}
- t = methtype(t);
+ t = methtype(t, 0);
if(t != T)
- expandmeth(t->sym, t);
+ expandmeth(t);
for(im=iface->type; im; im=im->down) {
imtype = methodfunc(im->type, 0);
tm = ifacelookdot(im->sym, t, &followptr, 0);
@@ -3626,23 +3624,23 @@ isbadimport(Strlit *path)
while(*s) {
s += chartorune(&r, s);
if(r == Runeerror) {
- yyerror("import path contains invalid UTF-8 sequence");
+ yyerror("import path contains invalid UTF-8 sequence: \"%Z\"", path);
return 1;
}
if(r < 0x20 || r == 0x7f) {
- yyerror("import path contains control character");
+ yyerror("import path contains control character: \"%Z\"", path);
return 1;
}
if(r == '\\') {
- yyerror("import path contains backslash; use slash");
+ yyerror("import path contains backslash; use slash: \"%Z\"", path);
return 1;
}
if(isspacerune(r)) {
- yyerror("import path contains space character");
+ yyerror("import path contains space character: \"%Z\"", path);
return 1;
}
- if(utfrune("!\"#$%&'()*,:;<=>?[]^`{|}~", r)) {
- yyerror("import path contains invalid character '%C'", r);
+ if(utfrune("!\"#$%&'()*,:;<=>?[]^`{|}", r)) {
+ yyerror("import path contains invalid character '%C': \"%Z\"", r, path);
return 1;
}
}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 90bd24964..e98d53857 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -190,6 +190,46 @@ typecheck(Node **np, int top)
return n;
}
+/*
+ * does n contain a call or receive operation?
+ */
+static int callrecvlist(NodeList*);
+
+static int
+callrecv(Node *n)
+{
+ if(n == nil)
+ return 0;
+
+ switch(n->op) {
+ case OCALL:
+ case OCALLMETH:
+ case OCALLINTER:
+ case OCALLFUNC:
+ case ORECV:
+ return 1;
+ }
+
+ return callrecv(n->left) ||
+ callrecv(n->right) ||
+ callrecv(n->ntest) ||
+ callrecv(n->nincr) ||
+ callrecvlist(n->ninit) ||
+ callrecvlist(n->nbody) ||
+ callrecvlist(n->nelse) ||
+ callrecvlist(n->list) ||
+ callrecvlist(n->rlist);
+}
+
+static int
+callrecvlist(NodeList *l)
+{
+ for(; l; l=l->next)
+ if(callrecv(l->n))
+ return 1;
+ return 0;
+}
+
static void
typecheck1(Node **np, int top)
{
@@ -995,12 +1035,14 @@ reswitch:
}
break;
case TARRAY:
- if(t->bound >= 0 && l->op == ONAME) {
- r = nod(OXXX, N, N);
- nodconst(r, types[TINT], t->bound);
- r->orig = n;
- n = r;
- }
+ if(t->bound < 0) // slice
+ break;
+ if(callrecv(l)) // has call or receive
+ break;
+ r = nod(OXXX, N, N);
+ nodconst(r, types[TINT], t->bound);
+ r->orig = n;
+ n = r;
break;
}
n->type = types[TINT];
@@ -1664,11 +1706,11 @@ looktypedot(Node *n, Type *t, int dostrcmp)
if(t->sym == S && isptr[t->etype])
tt = t->type;
- f2 = methtype(tt);
+ f2 = methtype(tt, 0);
if(f2 == T)
return 0;
- expandmeth(f2->sym, f2);
+ expandmeth(f2);
f2 = lookdot1(n, s, f2, f2->xmethod, dostrcmp);
if(f2 == T)
return 0;
@@ -1712,7 +1754,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
f2 = T;
if(n->left->type == t || n->left->type->sym == S) {
- f2 = methtype(t);
+ f2 = methtype(t, 0);
if(f2 != T) {
// Use f2->method, not f2->xmethod: adddot has
// already inserted all the necessary embedded dots.
@@ -1964,7 +2006,7 @@ keydup(Node *n, Node *hash[], ulong nhash)
b = cmp.val.u.bval;
if(b) {
// too lazy to print the literal
- yyerror("duplicate key in map literal");
+ yyerror("duplicate key %N in map literal", n);
return;
}
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 74298e126..7dfd34a7a 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -646,12 +646,6 @@ walkexpr(Node **np, NodeList **init)
n->ninit = nil;
l = n->list->n;
r = n->list->next->n;
- if(n->right != N) {
- // TODO: Remove once two-element map assigment is gone.
- l = safeexpr(l, init);
- r = safeexpr(r, init);
- safeexpr(n->right, init); // cause side effects from n->right
- }
t = l->type;
n = mkcall1(mapfndel("mapdelete", t), t->down, init, typename(t), l, r);
goto ret;
@@ -2364,6 +2358,12 @@ append(Node *n, NodeList **init)
walkexprlistsafe(n->list, init);
+ // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
+ // and n are name or literal, but those may index the slice we're
+ // modifying here. Fix explicitly.
+ for(l=n->list; l; l=l->next)
+ l->n = cheapexpr(l->n, init);
+
nsrc = n->list->n;
argc = count(n->list) - 1;
if (argc < 1) {
@@ -2520,6 +2520,7 @@ walkcompare(Node **np, NodeList **init)
expr = nodbool(n->op == OEQ);
typecheck(&expr, Erv);
walkexpr(&expr, init);
+ expr->type = n->type;
*np = expr;
return;
}
@@ -2540,6 +2541,7 @@ walkcompare(Node **np, NodeList **init)
expr = nodbool(n->op == OEQ);
typecheck(&expr, Erv);
walkexpr(&expr, init);
+ expr->type = n->type;
*np = expr;
return;
}