diff options
author | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2021-10-20 00:09:09 +0700 |
---|---|---|
committer | Cuong Manh Le <cuong.manhle.vn@gmail.com> | 2021-10-19 18:55:51 +0000 |
commit | d7149e502dfb13fdc94439eebaf1823a6c6dd84f (patch) | |
tree | 23721d86e90b6864f40ea35b2db92230555be446 /src/reflect/value.go | |
parent | d94498470bb09bb0606b0eff3248cb5b35e1a145 (diff) | |
download | go-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.go | 37 |
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. |