1// run
2
3// Copyright 2020 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// This test makes sure unsafe-uintptr arguments are handled correctly.
8
9package main
10
11import (
12	"runtime"
13	"unsafe"
14)
15
16var done = make(chan bool, 1)
17
18func setup() unsafe.Pointer {
19	s := "ok"
20	runtime.SetFinalizer(&s, func(p *string) { *p = "FAIL" })
21	return unsafe.Pointer(&s)
22}
23
24//go:noinline
25//go:uintptrescapes
26func test(s string, p, q uintptr, rest ...uintptr) int {
27	runtime.GC()
28	runtime.GC()
29
30	if *(*string)(unsafe.Pointer(p)) != "ok" {
31		panic(s + ": p failed")
32	}
33	if *(*string)(unsafe.Pointer(q)) != "ok" {
34		panic(s + ": q failed")
35	}
36	for _, r := range rest {
37		if *(*string)(unsafe.Pointer(r)) != "ok" {
38			panic(s + ": r[i] failed")
39		}
40	}
41
42	done <- true
43	return 0
44}
45
46//go:noinline
47func f() int {
48	return test("return", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
49}
50
51type S struct{}
52
53//go:noinline
54//go:uintptrescapes
55func (S) test(s string, p, q uintptr, rest ...uintptr) int {
56	return test(s, p, q, rest...)
57}
58
59func main() {
60	test("normal", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
61	<-done
62
63	go test("go", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
64	<-done
65
66	func() {
67		defer test("defer", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
68	}()
69	<-done
70
71	func() {
72		for {
73			defer test("defer in for loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
74			break
75		}
76	}()
77	<-done
78
79	func() {
80		s := &S{}
81		defer s.test("method call", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
82	}()
83	<-done
84
85	func() {
86		s := &S{}
87		for {
88			defer s.test("defer method loop", uintptr(setup()), uintptr(setup()), uintptr(setup()), uintptr(setup()))
89			break
90		}
91	}()
92	<-done
93
94	f()
95	<-done
96}
97