Skip to content

Commit d7149e5

Browse files
committed
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 <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent d944984 commit d7149e5

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

src/reflect/value.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1936,7 +1936,42 @@ func (v Value) OverflowUint(x uint64) bool {
19361936
//
19371937
// Deprecated: use uintptr(Value.UnsafePointer()) to get the equivalent result.
19381938
func (v Value) Pointer() uintptr {
1939-
return uintptr(v.UnsafePointer())
1939+
k := v.kind()
1940+
switch k {
1941+
case Ptr:
1942+
if v.typ.ptrdata == 0 {
1943+
// Handle pointers to go:notinheap types directly,
1944+
// so we never materialize such pointers as an
1945+
// unsafe.Pointer. (Such pointers are always indirect.)
1946+
// See issue 42076.
1947+
return *(*uintptr)(v.ptr)
1948+
}
1949+
fallthrough
1950+
case Chan, Map, UnsafePointer:
1951+
return uintptr(v.pointer())
1952+
case Func:
1953+
if v.flag&flagMethod != 0 {
1954+
// As the doc comment says, the returned pointer is an
1955+
// underlying code pointer but not necessarily enough to
1956+
// identify a single function uniquely. All method expressions
1957+
// created via reflect have the same underlying code pointer,
1958+
// so their Pointers are equal. The function used here must
1959+
// match the one used in makeMethodValue.
1960+
f := methodValueCall
1961+
return **(**uintptr)(unsafe.Pointer(&f))
1962+
}
1963+
p := v.pointer()
1964+
// Non-nil func value points at data block.
1965+
// First word of data block is actual code.
1966+
if p != nil {
1967+
p = *(*unsafe.Pointer)(p)
1968+
}
1969+
return uintptr(p)
1970+
1971+
case Slice:
1972+
return (*SliceHeader)(v.ptr).Data
1973+
}
1974+
panic(&ValueError{"reflect.Value.Pointer", v.kind()})
19401975
}
19411976

19421977
// Recv receives and returns a value from the channel v.

0 commit comments

Comments
 (0)