1
0
mirror of https://github.com/golang/go synced 2024-07-05 09:50:19 +00:00

all: add reflect.SliceAt function

Fixes #61308

Change-Id: Ic17d737fda055a60779985d5da497745c80d5cfa
Reviewed-on: https://go-review.googlesource.com/c/go/+/516597
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Cuong Manh Le 2023-08-08 12:58:33 +07:00 committed by Gopher Robot
parent 3d61f24835
commit d08a957298
5 changed files with 63 additions and 0 deletions

1
api/next/61308.txt Normal file
View File

@ -0,0 +1 @@
pkg reflect, func SliceAt(Type, unsafe.Pointer, int) Value #61308

View File

@ -0,0 +1,3 @@
The [`SliceAt(typ Type, p unsafe.Pointer, len int)`](/pkg/reflect#SliceAt) function
returns a Value representing a slice whose underlying array starts at p and whose
length and capacity are len.

View File

@ -8548,3 +8548,44 @@ func TestValuePointerAndUnsafePointer(t *testing.T) {
})
}
}
// Test cases copied from ../../test/unsafebuiltins.go
func TestSliceAt(t *testing.T) {
const maxUintptr = 1 << (8 * unsafe.Sizeof(uintptr(0)))
var p [10]byte
typ := TypeOf(p[0])
s := SliceAt(typ, unsafe.Pointer(&p[0]), len(p))
if s.Pointer() != uintptr(unsafe.Pointer(&p[0])) {
t.Fatalf("unexpected underlying array: %d, want: %d", s.Pointer(), uintptr(unsafe.Pointer(&p[0])))
}
if s.Len() != len(p) || s.Cap() != len(p) {
t.Fatalf("unexpected len or cap, len: %d, cap: %d, want: %d", s.Len(), s.Cap(), len(p))
}
typ = TypeOf(0)
if !SliceAt(typ, unsafe.Pointer((*int)(nil)), 0).IsNil() {
t.Fatal("nil pointer with zero length must return nil")
}
// nil pointer with positive length panics
shouldPanic("", func() { _ = SliceAt(typ, unsafe.Pointer((*int)(nil)), 1) })
// negative length
var neg int = -1
shouldPanic("", func() { _ = SliceAt(TypeOf(byte(0)), unsafe.Pointer(&p[0]), neg) })
// size overflows address space
n := uint64(0)
shouldPanic("", func() { _ = SliceAt(TypeOf(n), unsafe.Pointer(&n), maxUintptr/8) })
shouldPanic("", func() { _ = SliceAt(TypeOf(n), unsafe.Pointer(&n), maxUintptr/8+1) })
// sliced memory overflows address space
last := (*byte)(unsafe.Pointer(^uintptr(0)))
// This panics here, but won't panic in ../../test/unsafebuiltins.go,
// because unsafe.Slice(last, 1) does not escape.
//
// _ = SliceAt(typ, unsafe.Pointer(last), 1)
shouldPanic("", func() { _ = SliceAt(typ, unsafe.Pointer(last), 2) })
}

View File

@ -3211,6 +3211,16 @@ func MakeSlice(typ Type, len, cap int) Value {
return Value{&typ.(*rtype).t, unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
// SliceAt returns a [Value] representing a slice whose underlying
// data starts at p, with length and capacity equal to n.
//
// This is like [unsafe.Slice].
func SliceAt(typ Type, p unsafe.Pointer, n int) Value {
unsafeslice(typ.common(), p, n)
s := unsafeheader.Slice{Data: p, Len: n, Cap: n}
return Value{SliceOf(typ).common(), unsafe.Pointer(&s), flagIndir | flag(Slice)}
}
// MakeChan creates a new channel with the specified type and buffer size.
func MakeChan(typ Type, buffer int) Value {
if typ.Kind() != Chan {
@ -3978,6 +3988,9 @@ func verifyNotInHeapPtr(p uintptr) bool
//go:noescape
func growslice(t *abi.Type, old unsafeheader.Slice, num int) unsafeheader.Slice
//go:noescape
func unsafeslice(t *abi.Type, ptr unsafe.Pointer, len int)
// Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that
// the compiler cannot follow.

View File

@ -112,3 +112,8 @@ func panicunsafeslicenilptr1(pc uintptr) {
panicCheck1(pc, "unsafe.Slice: ptr is nil and len is not zero")
panic(errorString("unsafe.Slice: ptr is nil and len is not zero"))
}
//go:linkname reflect_unsafeslice reflect.unsafeslice
func reflect_unsafeslice(et *_type, ptr unsafe.Pointer, len int) {
unsafeslice(et, ptr, len)
}