mirror of
https://github.com/golang/go
synced 2024-11-24 17:50:15 -07:00
cmd/gc: unnamed struct types can have methods
Fixes #3143. R=ken2 CC=golang-dev https://golang.org/cl/5752070
This commit is contained in:
parent
712473612f
commit
4267974c0b
@ -1168,21 +1168,22 @@ methodsym(Sym *nsym, Type *t0, int iface)
|
|||||||
char *p;
|
char *p;
|
||||||
Type *t;
|
Type *t;
|
||||||
char *suffix;
|
char *suffix;
|
||||||
|
Pkg *spkg;
|
||||||
|
static Pkg *toppkg;
|
||||||
|
|
||||||
t = t0;
|
t = t0;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
goto bad;
|
goto bad;
|
||||||
s = t->sym;
|
s = t->sym;
|
||||||
if(s == S) {
|
if(s == S && isptr[t->etype]) {
|
||||||
if(!isptr[t->etype])
|
|
||||||
goto bad;
|
|
||||||
t = t->type;
|
t = t->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
goto bad;
|
goto bad;
|
||||||
s = t->sym;
|
s = t->sym;
|
||||||
if(s == S)
|
|
||||||
goto bad;
|
|
||||||
}
|
}
|
||||||
|
spkg = nil;
|
||||||
|
if(s != S)
|
||||||
|
spkg = s->pkg;
|
||||||
|
|
||||||
// if t0 == *t and t0 has a sym,
|
// if t0 == *t and t0 has a sym,
|
||||||
// we want to see *t, not t0, in the method name.
|
// we want to see *t, not t0, in the method name.
|
||||||
@ -1195,7 +1196,7 @@ methodsym(Sym *nsym, Type *t0, int iface)
|
|||||||
if(t0->width < types[tptr]->width)
|
if(t0->width < types[tptr]->width)
|
||||||
suffix = "·i";
|
suffix = "·i";
|
||||||
}
|
}
|
||||||
if(nsym->pkg != s->pkg && !exportname(nsym->name)) {
|
if((spkg == nil || nsym->pkg != spkg) && !exportname(nsym->name)) {
|
||||||
if(t0->sym == S && isptr[t0->etype])
|
if(t0->sym == S && isptr[t0->etype])
|
||||||
p = smprint("(%-hT).%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
|
p = smprint("(%-hT).%s.%s%s", t0, nsym->pkg->prefix, nsym->name, suffix);
|
||||||
else
|
else
|
||||||
@ -1206,7 +1207,12 @@ methodsym(Sym *nsym, Type *t0, int iface)
|
|||||||
else
|
else
|
||||||
p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
|
p = smprint("%-hT.%s%s", t0, nsym->name, suffix);
|
||||||
}
|
}
|
||||||
s = pkglookup(p, s->pkg);
|
if(spkg == nil) {
|
||||||
|
if(toppkg == nil)
|
||||||
|
toppkg = mkpkg(strlit("go"));
|
||||||
|
spkg = toppkg;
|
||||||
|
}
|
||||||
|
s = pkglookup(p, spkg);
|
||||||
free(p);
|
free(p);
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
@ -1275,7 +1281,7 @@ addmethod(Sym *sf, Type *t, int local)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pa = pa->type;
|
pa = pa->type;
|
||||||
f = methtype(pa);
|
f = methtype(pa, 1);
|
||||||
if(f == T) {
|
if(f == T) {
|
||||||
t = pa;
|
t = pa;
|
||||||
if(t != T) {
|
if(t != T) {
|
||||||
|
@ -1154,7 +1154,7 @@ int cplxsubtype(int et);
|
|||||||
int eqtype(Type *t1, Type *t2);
|
int eqtype(Type *t1, Type *t2);
|
||||||
int eqtypenoname(Type *t1, Type *t2);
|
int eqtypenoname(Type *t1, Type *t2);
|
||||||
void errorexit(void);
|
void errorexit(void);
|
||||||
void expandmeth(Sym *s, Type *t);
|
void expandmeth(Type *t);
|
||||||
void fatal(char *fmt, ...);
|
void fatal(char *fmt, ...);
|
||||||
void flusherrors(void);
|
void flusherrors(void);
|
||||||
void frame(int context);
|
void frame(int context);
|
||||||
@ -1192,7 +1192,7 @@ NodeList* listtreecopy(NodeList *l);
|
|||||||
Sym* lookup(char *name);
|
Sym* lookup(char *name);
|
||||||
void* mal(int32 n);
|
void* mal(int32 n);
|
||||||
Type* maptype(Type *key, Type *val);
|
Type* maptype(Type *key, Type *val);
|
||||||
Type* methtype(Type *t);
|
Type* methtype(Type *t, int mustname);
|
||||||
Pkg* mkpkg(Strlit *path);
|
Pkg* mkpkg(Strlit *path);
|
||||||
Sym* ngotype(Node *n);
|
Sym* ngotype(Node *n);
|
||||||
int noconv(Type *t1, Type *t2);
|
int noconv(Type *t1, Type *t2);
|
||||||
|
@ -144,11 +144,11 @@ methods(Type *t)
|
|||||||
Sig *a, *b;
|
Sig *a, *b;
|
||||||
Sym *method;
|
Sym *method;
|
||||||
|
|
||||||
// named method type
|
// method type
|
||||||
mt = methtype(t);
|
mt = methtype(t, 0);
|
||||||
if(mt == T)
|
if(mt == T)
|
||||||
return nil;
|
return nil;
|
||||||
expandmeth(mt->sym, mt);
|
expandmeth(mt);
|
||||||
|
|
||||||
// type stored in interface word
|
// type stored in interface word
|
||||||
it = t;
|
it = t;
|
||||||
|
@ -944,7 +944,7 @@ isideal(Type *t)
|
|||||||
* return type to hang methods off (r).
|
* return type to hang methods off (r).
|
||||||
*/
|
*/
|
||||||
Type*
|
Type*
|
||||||
methtype(Type *t)
|
methtype(Type *t, int mustname)
|
||||||
{
|
{
|
||||||
if(t == T)
|
if(t == T)
|
||||||
return T;
|
return T;
|
||||||
@ -959,7 +959,7 @@ methtype(Type *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// need a type name
|
// need a type name
|
||||||
if(t->sym == S)
|
if(t->sym == S && (mustname || t->etype != TSTRUCT))
|
||||||
return T;
|
return T;
|
||||||
|
|
||||||
// check types
|
// check types
|
||||||
@ -2101,7 +2101,7 @@ lookdot0(Sym *s, Type *t, Type **save, int ignorecase)
|
|||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u = methtype(t);
|
u = methtype(t, 0);
|
||||||
if(u != T) {
|
if(u != T) {
|
||||||
for(f=u->method; f!=T; f=f->down)
|
for(f=u->method; f!=T; f=f->down)
|
||||||
if(f->embedded == 0 && (f->sym == s || (ignorecase && ucistrcmp(f->sym->name, s->name) == 0))) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u = methtype(t);
|
u = methtype(t, 0);
|
||||||
if(u != T) {
|
if(u != T) {
|
||||||
for(f=u->method; f!=T; f=f->down) {
|
for(f=u->method; f!=T; f=f->down) {
|
||||||
if(f->sym->flags & SymUniq)
|
if(f->sym->flags & SymUniq)
|
||||||
@ -2301,14 +2301,12 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
expandmeth(Sym *s, Type *t)
|
expandmeth(Type *t)
|
||||||
{
|
{
|
||||||
Symlink *sl;
|
Symlink *sl;
|
||||||
Type *f;
|
Type *f;
|
||||||
int c, d;
|
int c, d;
|
||||||
|
|
||||||
if(s == S)
|
|
||||||
return;
|
|
||||||
if(t == T || t->xmethod != nil)
|
if(t == T || t->xmethod != nil)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -3021,9 +3019,9 @@ implements(Type *t, Type *iface, Type **m, Type **samename, int *ptr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t = methtype(t);
|
t = methtype(t, 0);
|
||||||
if(t != T)
|
if(t != T)
|
||||||
expandmeth(t->sym, t);
|
expandmeth(t);
|
||||||
for(im=iface->type; im; im=im->down) {
|
for(im=iface->type; im; im=im->down) {
|
||||||
imtype = methodfunc(im->type, 0);
|
imtype = methodfunc(im->type, 0);
|
||||||
tm = ifacelookdot(im->sym, t, &followptr, 0);
|
tm = ifacelookdot(im->sym, t, &followptr, 0);
|
||||||
|
@ -1664,11 +1664,11 @@ looktypedot(Node *n, Type *t, int dostrcmp)
|
|||||||
if(t->sym == S && isptr[t->etype])
|
if(t->sym == S && isptr[t->etype])
|
||||||
tt = t->type;
|
tt = t->type;
|
||||||
|
|
||||||
f2 = methtype(tt);
|
f2 = methtype(tt, 0);
|
||||||
if(f2 == T)
|
if(f2 == T)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
expandmeth(f2->sym, f2);
|
expandmeth(f2);
|
||||||
f2 = lookdot1(n, s, f2, f2->xmethod, dostrcmp);
|
f2 = lookdot1(n, s, f2, f2->xmethod, dostrcmp);
|
||||||
if(f2 == T)
|
if(f2 == T)
|
||||||
return 0;
|
return 0;
|
||||||
@ -1712,7 +1712,7 @@ lookdot(Node *n, Type *t, int dostrcmp)
|
|||||||
|
|
||||||
f2 = T;
|
f2 = T;
|
||||||
if(n->left->type == t || n->left->type->sym == S) {
|
if(n->left->type == t || n->left->type->sym == S) {
|
||||||
f2 = methtype(t);
|
f2 = methtype(t, 0);
|
||||||
if(f2 != T) {
|
if(f2 != T) {
|
||||||
// Use f2->method, not f2->xmethod: adddot has
|
// Use f2->method, not f2->xmethod: adddot has
|
||||||
// already inserted all the necessary embedded dots.
|
// already inserted all the necessary embedded dots.
|
||||||
|
@ -72,4 +72,28 @@ func main() {
|
|||||||
}
|
}
|
||||||
println("BUG: myT3:", i.m(), "called")
|
println("BUG: myT3:", i.m(), "called")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var t4 struct {
|
||||||
|
localT
|
||||||
|
lib.T
|
||||||
|
}
|
||||||
|
if t4.m() != "main.localT.m" {
|
||||||
|
println("BUG: t4:", t4.m(), "called")
|
||||||
|
}
|
||||||
|
i = &t4
|
||||||
|
if i.m() != "main.localT.m" {
|
||||||
|
println("BUG: myT4:", i.m(), "called")
|
||||||
|
}
|
||||||
|
|
||||||
|
var t5 struct {
|
||||||
|
lib.T
|
||||||
|
localT
|
||||||
|
}
|
||||||
|
if t5.m() != "main.localT.m" {
|
||||||
|
println("BUG: t5:", t5.m(), "called")
|
||||||
|
}
|
||||||
|
i = &t5
|
||||||
|
if i.m() != "main.localT.m" {
|
||||||
|
println("BUG: myT5:", i.m(), "called")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
132
test/method.go
132
test/method.go
@ -94,27 +94,27 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if val(s) != 1 {
|
if val(s) != 1 {
|
||||||
println("s.val:", val(s))
|
println("val(s):", val(s))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
if val(ps) != 2 {
|
if val(ps) != 2 {
|
||||||
println("ps.val:", val(ps))
|
println("val(ps):", val(ps))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
if val(i) != 3 {
|
if val(i) != 3 {
|
||||||
println("i.val:", val(i))
|
println("val(i):", val(i))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
if val(pi) != 4 {
|
if val(pi) != 4 {
|
||||||
println("pi.val:", val(pi))
|
println("val(pi):", val(pi))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
if val(t) != 7 {
|
if val(t) != 7 {
|
||||||
println("t.val:", val(t))
|
println("val(t):", val(t))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
if val(pt) != 8 {
|
if val(pt) != 8 {
|
||||||
println("pt.val:", val(pt))
|
println("val(pt):", val(pt))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,4 +127,124 @@ func main() {
|
|||||||
println("Val.val(v):", Val.val(v))
|
println("Val.val(v):", Val.val(v))
|
||||||
panic("fail")
|
panic("fail")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var zs struct { S }
|
||||||
|
var zps struct { *S1 }
|
||||||
|
var zi struct { I }
|
||||||
|
var zpi struct { *I1 }
|
||||||
|
var zpt struct { *T1 }
|
||||||
|
var zt struct { T }
|
||||||
|
var zv struct { Val }
|
||||||
|
|
||||||
|
if zs.val() != 1 {
|
||||||
|
println("zs.val:", zs.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if zps.val() != 2 {
|
||||||
|
println("zps.val:", zps.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if zi.val() != 3 {
|
||||||
|
println("zi.val:", zi.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if zpi.val() != 4 {
|
||||||
|
println("zpi.val:", zpi.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if zt.val() != 7 {
|
||||||
|
println("zt.val:", zt.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if zpt.val() != 8 {
|
||||||
|
println("zpt.val:", zpt.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
if val(zs) != 1 {
|
||||||
|
println("val(zs):", val(zs))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(zps) != 2 {
|
||||||
|
println("val(zps):", val(zps))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(zi) != 3 {
|
||||||
|
println("val(zi):", val(zi))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(zpi) != 4 {
|
||||||
|
println("val(zpi):", val(zpi))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(zt) != 7 {
|
||||||
|
println("val(zt):", val(zt))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(zpt) != 8 {
|
||||||
|
println("val(zpt):", val(zpt))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
zv.Val = zi
|
||||||
|
if zv.val() != 3 {
|
||||||
|
println("zv.val():", zv.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&zs).val() != 1 {
|
||||||
|
println("(&zs).val:", (&zs).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if (&zps).val() != 2 {
|
||||||
|
println("(&zps).val:", (&zps).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if (&zi).val() != 3 {
|
||||||
|
println("(&zi).val:", (&zi).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if (&zpi).val() != 4 {
|
||||||
|
println("(&zpi).val:", (&zpi).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if (&zt).val() != 7 {
|
||||||
|
println("(&zt).val:", (&zt).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if (&zpt).val() != 8 {
|
||||||
|
println("(&zpt).val:", (&zpt).val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
if val(&zs) != 1 {
|
||||||
|
println("val(&zs):", val(&zs))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(&zps) != 2 {
|
||||||
|
println("val(&zps):", val(&zps))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(&zi) != 3 {
|
||||||
|
println("val(&zi):", val(&zi))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(&zpi) != 4 {
|
||||||
|
println("val(&zpi):", val(&zpi))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(&zt) != 7 {
|
||||||
|
println("val(&zt):", val(&zt))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
if val(&zpt) != 8 {
|
||||||
|
println("val(&zpt):", val(&zpt))
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
zv.Val = &zi
|
||||||
|
if zv.val() != 3 {
|
||||||
|
println("zv.val():", zv.val())
|
||||||
|
panic("fail")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user