1// errorcheck -0 -m -l
2
3// Copyright 2019 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// Test escape analysis for unsafe.Pointer rules.
8
9package escape
10
11import (
12	"reflect"
13	"unsafe"
14)
15
16// (1) Conversion of a *T1 to Pointer to *T2.
17
18func convert(p *float64) *uint64 { // ERROR "leaking param: p to result ~r0 level=0$"
19	return (*uint64)(unsafe.Pointer(p))
20}
21
22// (3) Conversion of a Pointer to a uintptr and back, with arithmetic.
23
24func arithAdd() unsafe.Pointer {
25	var x [2]byte // ERROR "moved to heap: x"
26	return unsafe.Pointer(uintptr(unsafe.Pointer(&x[0])) + 1)
27}
28
29func arithSub() unsafe.Pointer {
30	var x [2]byte // ERROR "moved to heap: x"
31	return unsafe.Pointer(uintptr(unsafe.Pointer(&x[1])) - 1)
32}
33
34func arithMask() unsafe.Pointer {
35	var x [2]byte // ERROR "moved to heap: x"
36	return unsafe.Pointer(uintptr(unsafe.Pointer(&x[1])) &^ 1)
37}
38
39// (5) Conversion of the result of reflect.Value.Pointer or
40// reflect.Value.UnsafeAddr from uintptr to Pointer.
41
42// BAD: should be "leaking param: p to result ~r0 level=0$"
43func valuePointer(p *int) unsafe.Pointer { // ERROR "leaking param: p$"
44	return unsafe.Pointer(reflect.ValueOf(p).Pointer())
45}
46
47// BAD: should be "leaking param: p to result ~r0 level=0$"
48func valueUnsafeAddr(p *int) unsafe.Pointer { // ERROR "leaking param: p$"
49	return unsafe.Pointer(reflect.ValueOf(p).Elem().UnsafeAddr())
50}
51
52// (6) Conversion of a reflect.SliceHeader or reflect.StringHeader
53// Data field to or from Pointer.
54
55func fromSliceData(s []int) unsafe.Pointer { // ERROR "leaking param: s to result ~r0 level=0$"
56	return unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s)).Data)
57}
58
59func fromStringData(s string) unsafe.Pointer { // ERROR "leaking param: s to result ~r0 level=0$"
60	return unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&s)).Data)
61}
62
63func toSliceData(s *[]int, p unsafe.Pointer) { // ERROR "s does not escape" "leaking param: p$"
64	(*reflect.SliceHeader)(unsafe.Pointer(s)).Data = uintptr(p)
65}
66
67func toStringData(s *string, p unsafe.Pointer) { // ERROR "s does not escape" "leaking param: p$"
68	(*reflect.StringHeader)(unsafe.Pointer(s)).Data = uintptr(p)
69}
70