|  | // run | 
|  |  | 
|  | // Copyright 2019 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // Test that //go:uintptrescapes works for methods. | 
|  |  | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  | "runtime" | 
|  | "unsafe" | 
|  | ) | 
|  |  | 
|  | var callback func() | 
|  |  | 
|  | //go:noinline | 
|  | //go:uintptrescapes | 
|  | func F(ptr uintptr) { callback() } | 
|  |  | 
|  | //go:noinline | 
|  | //go:uintptrescapes | 
|  | func Fv(ptrs ...uintptr) { callback() } | 
|  |  | 
|  | type T struct{} | 
|  |  | 
|  | //go:noinline | 
|  | //go:uintptrescapes | 
|  | func (T) M(ptr uintptr) { callback() } | 
|  |  | 
|  | //go:noinline | 
|  | //go:uintptrescapes | 
|  | func (T) Mv(ptrs ...uintptr) { callback() } | 
|  |  | 
|  | // Each test should pass uintptr(ptr) as an argument to a function call, | 
|  | // which in turn should call callback. The callback checks that ptr is kept alive. | 
|  | var tests = []func(ptr unsafe.Pointer){ | 
|  | func(ptr unsafe.Pointer) { F(uintptr(ptr)) }, | 
|  | func(ptr unsafe.Pointer) { Fv(uintptr(ptr)) }, | 
|  | func(ptr unsafe.Pointer) { T{}.M(uintptr(ptr)) }, | 
|  | func(ptr unsafe.Pointer) { T{}.Mv(uintptr(ptr)) }, | 
|  | } | 
|  |  | 
|  | func main() { | 
|  | for i, test := range tests { | 
|  | finalized := false | 
|  |  | 
|  | ptr := new([64]byte) | 
|  | runtime.SetFinalizer(ptr, func(*[64]byte) { | 
|  | finalized = true | 
|  | }) | 
|  |  | 
|  | callback = func() { | 
|  | runtime.GC() | 
|  | if finalized { | 
|  | fmt.Printf("test #%d failed\n", i) | 
|  | } | 
|  | } | 
|  | test(unsafe.Pointer(ptr)) | 
|  | } | 
|  | } |