Skip to content

Commit 3d61f24

Browse files
cuonglmgopherbot
authored andcommitted
reflect: handle String kind in Value.{Pointer,UnsafePointer}
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]>
1 parent e074fcc commit 3d61f24

File tree

2 files changed

+47
-3
lines changed

2 files changed

+47
-3
lines changed

src/reflect/all_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8512,3 +8512,39 @@ func TestClear(t *testing.T) {
85128512
})
85138513
}
85148514
}
8515+
8516+
func TestValuePointerAndUnsafePointer(t *testing.T) {
8517+
ptr := new(int)
8518+
ch := make(chan int)
8519+
m := make(map[int]int)
8520+
unsafePtr := unsafe.Pointer(ptr)
8521+
slice := make([]int, 1)
8522+
fn := func() {}
8523+
s := "foo"
8524+
8525+
tests := []struct {
8526+
name string
8527+
val Value
8528+
wantUnsafePointer unsafe.Pointer
8529+
}{
8530+
{"pointer", ValueOf(ptr), unsafe.Pointer(ptr)},
8531+
{"channel", ValueOf(ch), *(*unsafe.Pointer)(unsafe.Pointer(&ch))},
8532+
{"map", ValueOf(m), *(*unsafe.Pointer)(unsafe.Pointer(&m))},
8533+
{"unsafe.Pointer", ValueOf(unsafePtr), unsafePtr},
8534+
{"function", ValueOf(fn), **(**unsafe.Pointer)(unsafe.Pointer(&fn))},
8535+
{"slice", ValueOf(slice), unsafe.Pointer(unsafe.SliceData(slice))},
8536+
{"string", ValueOf(s), unsafe.Pointer(unsafe.StringData(s))},
8537+
}
8538+
8539+
for _, tc := range tests {
8540+
tc := tc
8541+
t.Run(tc.name, func(t *testing.T) {
8542+
if got := tc.val.Pointer(); got != uintptr(tc.wantUnsafePointer) {
8543+
t.Errorf("unexpected uintptr result, got %#x, want %#x", got, uintptr(tc.wantUnsafePointer))
8544+
}
8545+
if got := tc.val.UnsafePointer(); got != tc.wantUnsafePointer {
8546+
t.Errorf("unexpected unsafe.Pointer result, got %#x, want %#x", got, tc.wantUnsafePointer)
8547+
}
8548+
})
8549+
}
8550+
}

src/reflect/value.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2184,7 +2184,7 @@ func (v Value) OverflowUint(x uint64) bool {
21842184
// and make an exception.
21852185

21862186
// Pointer returns v's value as a uintptr.
2187-
// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], or [UnsafePointer].
2187+
// It panics if v's Kind is not [Chan], [Func], [Map], [Pointer], [Slice], [String], or [UnsafePointer].
21882188
//
21892189
// If v's Kind is [Func], the returned pointer is an underlying
21902190
// code pointer, but not necessarily enough to identify a
@@ -2195,6 +2195,9 @@ func (v Value) OverflowUint(x uint64) bool {
21952195
// element of the slice. If the slice is nil the returned value
21962196
// is 0. If the slice is empty but non-nil the return value is non-zero.
21972197
//
2198+
// If v's Kind is [String], the returned pointer is to the first
2199+
// element of the underlying bytes of string.
2200+
//
21982201
// It's preferred to use uintptr(Value.UnsafePointer()) to get the equivalent result.
21992202
func (v Value) Pointer() uintptr {
22002203
// The compiler loses track as it converts to uintptr. Force escape.
@@ -2232,9 +2235,10 @@ func (v Value) Pointer() uintptr {
22322235
p = *(*unsafe.Pointer)(p)
22332236
}
22342237
return uintptr(p)
2235-
22362238
case Slice:
22372239
return uintptr((*unsafeheader.Slice)(v.ptr).Data)
2240+
case String:
2241+
return uintptr((*unsafeheader.String)(v.ptr).Data)
22382242
}
22392243
panic(&ValueError{"reflect.Value.Pointer", v.kind()})
22402244
}
@@ -2779,6 +2783,9 @@ func (v Value) UnsafeAddr() uintptr {
27792783
// If v's Kind is [Slice], the returned pointer is to the first
27802784
// element of the slice. If the slice is nil the returned value
27812785
// is nil. If the slice is empty but non-nil the return value is non-nil.
2786+
//
2787+
// If v's Kind is [String], the returned pointer is to the first
2788+
// element of the underlying bytes of string.
27822789
func (v Value) UnsafePointer() unsafe.Pointer {
27832790
k := v.kind()
27842791
switch k {
@@ -2812,9 +2819,10 @@ func (v Value) UnsafePointer() unsafe.Pointer {
28122819
p = *(*unsafe.Pointer)(p)
28132820
}
28142821
return p
2815-
28162822
case Slice:
28172823
return (*unsafeheader.Slice)(v.ptr).Data
2824+
case String:
2825+
return (*unsafeheader.String)(v.ptr).Data
28182826
}
28192827
panic(&ValueError{"reflect.Value.UnsafePointer", v.kind()})
28202828
}

0 commit comments

Comments
 (0)