cmd/compile: fix method expressions with anonymous receivers

Method expressions with anonymous receiver types like "struct { T }.m"
require wrapper functions, which we weren't always creating. This in
turn resulted in linker errors.

This CL ensures that we generate wrapper functions for any anonymous
receiver types used in a method expression.

Fixes #22444.

Change-Id: Ia8ac27f238c2898965e57b82a91d959792d2ddd4
Reviewed-on: https://go-review.googlesource.com/105044
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Matthew Dempsky 2018-04-05 22:42:16 -07:00
parent 84b784a84f
commit 950a56899a
3 changed files with 14 additions and 4 deletions

View file

@ -1474,6 +1474,7 @@ func itabsym(it *obj.LSym, offset int64) *obj.LSym {
return syms[methodnum] return syms[methodnum]
} }
// addsignat ensures that a runtime type descriptor is emitted for t.
func addsignat(t *types.Type) { func addsignat(t *types.Type) {
signatset[t] = struct{}{} signatset[t] = struct{}{}
} }

View file

@ -2378,6 +2378,16 @@ func looktypedot(n *Node, t *types.Type, dostrcmp int) bool {
return false return false
} }
// The method expression T.m requires a wrapper when T is
// different from m's declared receiver type. We normally
// generate these wrappers while writing out runtime type
// descriptors, which is always done for types declared at
// package scope. However, we need to make sure to generate
// wrappers for anonymous receiver types too.
if mt.Sym == nil {
addsignat(t)
}
n.Sym = methodSym(t, n.Sym) n.Sym = methodSym(t, n.Sym)
n.Xoffset = f2.Offset n.Xoffset = f2.Offset
n.Type = f2.Type n.Type = f2.Type

View file

@ -45,10 +45,9 @@ func main() {
interface{ m1(string) }.m1(x, "d") interface{ m1(string) }.m1(x, "d")
want += " m1(d)" want += " m1(d)"
// cannot link the call below - see #22444 g := struct{ T }.m2
// g := struct{ T }.m2 g(struct{ T }{})
// g(struct{T}{}) want += " m2()"
// want += " m2()"
if got != want { if got != want {
panic("got" + got + ", want" + want) panic("got" + got + ", want" + want)