1// run 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 that //go:uintptrescapes works for methods. 8 9package main 10 11import ( 12 "fmt" 13 "runtime" 14 "unsafe" 15) 16 17var callback func() 18 19//go:noinline 20//go:uintptrescapes 21func F(ptr uintptr) { callback() } 22 23//go:noinline 24//go:uintptrescapes 25func Fv(ptrs ...uintptr) { callback() } 26 27type T struct{} 28 29//go:noinline 30//go:uintptrescapes 31func (T) M(ptr uintptr) { callback() } 32 33//go:noinline 34//go:uintptrescapes 35func (T) Mv(ptrs ...uintptr) { callback() } 36 37// Each test should pass uintptr(ptr) as an argument to a function call, 38// which in turn should call callback. The callback checks that ptr is kept alive. 39var tests = []func(ptr unsafe.Pointer){ 40 func(ptr unsafe.Pointer) { F(uintptr(ptr)) }, 41 func(ptr unsafe.Pointer) { Fv(uintptr(ptr)) }, 42 func(ptr unsafe.Pointer) { T{}.M(uintptr(ptr)) }, 43 func(ptr unsafe.Pointer) { T{}.Mv(uintptr(ptr)) }, 44} 45 46func main() { 47 for i, test := range tests { 48 finalized := false 49 50 ptr := new([64]byte) 51 runtime.SetFinalizer(ptr, func(*[64]byte) { 52 finalized = true 53 }) 54 55 callback = func() { 56 runtime.GC() 57 if finalized { 58 fmt.Printf("test #%d failed\n", i) 59 } 60 } 61 test(unsafe.Pointer(ptr)) 62 } 63} 64