mirror of
https://github.com/golang/go
synced 2024-11-11 17:11:36 -07:00
cmd/compile: when marking REFLECTMETHOD, check for reflect package itself
reflect.Type.Method (and MethodByName) can be used to obtain a reference of a method by reflection. The linker needs to know if reflect.Type.Method is called, and retain all exported methods accordingly. This is handled by the compiler, which marks the caller of reflect.Type.Method with REFLECTMETHOD attribute. The current code failed to handle the reflect package itself, so the method wrapper reflect.Type.Method is not marked. This CL fixes it. Fixes #38515. Change-Id: I12904d23eda664cf1794bc3676152f3218fb762b Reviewed-on: https://go-review.googlesource.com/c/go/+/228880 Run-TryBot: Cherry Zhang <cherryyz@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
de2318e3c6
commit
a32262d462
@ -3658,7 +3658,8 @@ func usemethod(n *Node) {
|
||||
|
||||
// Note: Don't rely on res0.Type.String() since its formatting depends on multiple factors
|
||||
// (including global variables such as numImports - was issue #19028).
|
||||
if s := res0.Type.Sym; s != nil && s.Name == "Method" && s.Pkg != nil && s.Pkg.Path == "reflect" {
|
||||
// Also need to check for reflect package itself (see Issue #38515).
|
||||
if s := res0.Type.Sym; s != nil && s.Name == "Method" && s.Pkg != nil && (s.Pkg.Path == "reflect" || s.Pkg == localpkg && myimportpath == "reflect") {
|
||||
Curfn.Func.SetReflectMethod(true)
|
||||
}
|
||||
}
|
||||
|
30
test/reflectmethod5.go
Normal file
30
test/reflectmethod5.go
Normal file
@ -0,0 +1,30 @@
|
||||
// run
|
||||
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 38515: failed to mark the method wrapper
|
||||
// reflect.Type.Method itself as REFLECTMETHOD.
|
||||
|
||||
package main
|
||||
|
||||
import "reflect"
|
||||
|
||||
var called bool
|
||||
|
||||
type foo struct{}
|
||||
|
||||
func (foo) X() { called = true }
|
||||
|
||||
var h = reflect.Type.Method
|
||||
|
||||
func main() {
|
||||
v := reflect.ValueOf(foo{})
|
||||
m := h(v.Type(), 0)
|
||||
f := m.Func.Interface().(func(foo))
|
||||
f(foo{})
|
||||
if !called {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
32
test/reflectmethod6.go
Normal file
32
test/reflectmethod6.go
Normal file
@ -0,0 +1,32 @@
|
||||
// run
|
||||
|
||||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Similar to reflectmethod5.go, but for reflect.Type.MethodByName.
|
||||
|
||||
package main
|
||||
|
||||
import "reflect"
|
||||
|
||||
var called bool
|
||||
|
||||
type foo struct{}
|
||||
|
||||
func (foo) X() { called = true }
|
||||
|
||||
var h = reflect.Type.MethodByName
|
||||
|
||||
func main() {
|
||||
v := reflect.ValueOf(foo{})
|
||||
m, ok := h(v.Type(), "X")
|
||||
if !ok {
|
||||
panic("FAIL")
|
||||
}
|
||||
f := m.Func.Interface().(func(foo))
|
||||
f(foo{})
|
||||
if !called {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user