Skip to content

Commit

Permalink
reflect: handle String kind in Value.{Pointer,UnsafePointer}
Browse files Browse the repository at this point in the history
Updates #61308

Change-Id: I92d459383c520d137787ce5c8f135d205af74e5d
Reviewed-on: https://go-review.googlesource.com/c/go/+/516596
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
Auto-Submit: Cuong Manh Le <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
cuonglm authored and gopherbot committed Apr 2, 2024
1 parent e074fcc commit 3d61f24
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
36 changes: 36 additions & 0 deletions src/reflect/all_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8512,3 +8512,39 @@ func TestClear(t *testing.T) {
})
}
}

func TestValuePointerAndUnsafePointer(t *testing.T) {
ptr := new(int)
ch := make(chan int)
m := make(map[int]int)
unsafePtr := unsafe.Pointer(ptr)
slice := make([]int, 1)
fn := func() {}
s := "foo"

tests := []struct {
name string
val Value
wantUnsafePointer unsafe.Pointer
}{
{"pointer", ValueOf(ptr), unsafe.Pointer(ptr)},
{"channel", ValueOf(ch), *(*unsafe.Pointer)(unsafe.Pointer(&ch))},
{"map", ValueOf(m), *(*unsafe.Pointer)(unsafe.Pointer(&m))},
{"unsafe.Pointer", ValueOf(unsafePtr), unsafePtr},
{"function", ValueOf(fn), **(**unsafe.Pointer)(unsafe.Pointer(&fn))},
{"slice", ValueOf(slice), unsafe.Pointer(unsafe.SliceData(slice))},
{"string", ValueOf(s), unsafe.Pointer(unsafe.StringData(s))},
}

for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
if got := tc.val.Pointer(); got != uintptr(tc.wantUnsafePointer) {
t.Errorf("unexpected uintptr result, got %#x, want %#x", got, uintptr(tc.wantUnsafePointer))
}
if got := tc.val.UnsafePointer(); got != tc.wantUnsafePointer {
t.Errorf("unexpected unsafe.Pointer result, got %#x, want %#x", got, tc.wantUnsafePointer)
}
})
}
}
14 changes: 11 additions & 3 deletions src/reflect/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -2184,7 +2184,7 @@ func (v Value) OverflowUint(x uint64) bool {
// and make an exception.

// Pointer returns v's value as a uintptr.
// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], or [UnsafePointer].
// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], [String], or [UnsafePointer].
//
// If v's Kind is [Func], the returned pointer is an underlying
// code pointer, but not necessarily enough to identify a
Expand All @@ -2195,6 +2195,9 @@ func (v Value) OverflowUint(x uint64) bool {
// element of the slice. If the slice is nil the returned value
// is 0. If the slice is empty but non-nil the return value is non-zero.
//
// If v's Kind is [String], the returned pointer is to the first
// element of the underlying bytes of string.
//
// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
func (v Value) Pointer() uintptr {
// The compiler loses track as it converts to uintptr. Force escape.
Expand Down Expand Up @@ -2232,9 +2235,10 @@ func (v Value) Pointer() uintptr {
p = *(*unsafe.Pointer)(p)
}
return uintptr(p)

case Slice:
return uintptr((*unsafeheader.Slice)(v.ptr).Data)
case String:
return uintptr((*unsafeheader.String)(v.ptr).Data)
}
panic(&ValueError{"reflect.Value.Pointer", v.kind()})
}
Expand Down Expand Up @@ -2779,6 +2783,9 @@ func (v Value) UnsafeAddr() uintptr {
// If v's Kind is [Slice], the returned pointer is to the first
// element of the slice. If the slice is nil the returned value
// is nil. If the slice is empty but non-nil the return value is non-nil.
//
// If v's Kind is [String], the returned pointer is to the first
// element of the underlying bytes of string.
func (v Value) UnsafePointer() unsafe.Pointer {
k := v.kind()
switch k {
Expand Down Expand Up @@ -2812,9 +2819,10 @@ func (v Value) UnsafePointer() unsafe.Pointer {
p = *(*unsafe.Pointer)(p)
}
return p

case Slice:
return (*unsafeheader.Slice)(v.ptr).Data
case String:
return (*unsafeheader.String)(v.ptr).Data
}
panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
}
Expand Down

0 comments on commit 3d61f24

Please sign in to comment.