aboutsummaryrefslogtreecommitdiff
path: root/src/reflect/value.go
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2021-10-20 00:09:09 +0700
committerCuong Manh Le <cuong.manhle.vn@gmail.com>2021-10-19 18:55:51 +0000
commitd7149e502dfb13fdc94439eebaf1823a6c6dd84f (patch)
tree23721d86e90b6864f40ea35b2db92230555be446 /src/reflect/value.go
parentd94498470bb09bb0606b0eff3248cb5b35e1a145 (diff)
downloadgo-d7149e502dfb13fdc94439eebaf1823a6c6dd84f.tar.gz
go-d7149e502dfb13fdc94439eebaf1823a6c6dd84f.zip
reflect: restore Value.Pointer implementation
CL 350691 added Value.UnsafePointer and make Value.Pointer call it internally. It has a downside that Value.Pointer can now eligible to be inlined, thus making un-intentional side effect, like the test in fixedbugs/issue15329.go becomes flaky. This CL restore Value.Pointer original implementation, pre CL 350691, with the deprecation TODO removed. Fixes #49067 Change-Id: I735af182f8e729294333ca906ffc062f477cfc99 Reviewed-on: https://go-review.googlesource.com/c/go/+/356949 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/reflect/value.go')
-rw-r--r--src/reflect/value.go37
1 files changed, 36 insertions, 1 deletions
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 1d385f6bf9..63faa04964 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -1936,7 +1936,42 @@ func (v Value) OverflowUint(x uint64) bool {
//
// Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result.
func (v Value) Pointer() uintptr {
- return uintptr(v.UnsafePointer())
+ k := v.kind()
+ switch k {
+ case Ptr:
+ if v.typ.ptrdata == 0 {
+ // Handle pointers to go:notinheap types directly,
+ // so we never materialize such pointers as an
+ // unsafe.Pointer. (Such pointers are always indirect.)
+ // See issue 42076.
+ return *(*uintptr)(v.ptr)
+ }
+ fallthrough
+ case Chan, Map, UnsafePointer:
+ return uintptr(v.pointer())
+ case Func:
+ if v.flag&flagMethod != 0 {
+ // As the doc comment says, the returned pointer is an
+ // underlying code pointer but not necessarily enough to
+ // identify a single function uniquely. All method expressions
+ // created via reflect have the same underlying code pointer,
+ // so their Pointers are equal. The function used here must
+ // match the one used in makeMethodValue.
+ f := methodValueCall
+ return **(**uintptr)(unsafe.Pointer(&f))
+ }
+ p := v.pointer()
+ // Non-nil func value points at data block.
+ // First word of data block is actual code.
+ if p != nil {
+ p = *(*unsafe.Pointer)(p)
+ }
+ return uintptr(p)
+
+ case Slice:
+ return (*SliceHeader)(v.ptr).Data
+ }
+ panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}
// Recv receives and returns a value from the channel v.