// run // Copyright 2020 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. // This test makes sure unsafe-uintptr arguments are handled correctly. package main import ( "runtime" "unsafe" ) var done = make(chan bool, 1) func setup() unsafe.Pointer { s := "ok" runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" }) return unsafe.Pointer(&s) } //go:noinline //go:uintptrescapes func test(s string, p, q uintptr, rest ...uintptr) int { runtime.GC() runtime.GC() if *(*string)(unsafe.Pointer(p)) != "ok" { panic(s + ": p failed") } if *(*string)(unsafe.Pointer(q)) != "ok" { panic(s + ": q failed") } for _, r := range rest { if *(*string)(unsafe.Pointer(r)) != "ok" { panic(s + ": r[i] failed") } } done <- true return 0 } //go:noinline func f() int { return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) } type S struct{} //go:noinline //go:uintptrescapes func (S) test(s string, p, q uintptr, rest ...uintptr) int { return test(s, p, q, rest...) } func main() { test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) <-done go test("go", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) <-done func() { defer test("defer", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) }() <-done func() { for { defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) break } }() <-done func() { s := &S{} defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) }() <-done func() { s := &S{} for { defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup())) break } }() <-done f() <-done }