1// errorcheck -0 -m -l
2
3// Copyright 2012 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, using compiler diagnostic flags, that the escape analysis is working.
8// Compiles but does not run.  Inlining is disabled.
9
10package foo
11
12func noleak(p *int) int { // ERROR "p does not escape"
13	return *p
14}
15
16func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
17	return p
18}
19
20func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2"
21	return p, p
22}
23
24func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3"
25	return p, q
26}
27
28func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
29	return leaktoret22(q, p)
30}
31
32func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2"
33	r, s := leaktoret22(q, p)
34	return r, s
35}
36
37func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
38	r, s = leaktoret22(q, p)
39	return
40}
41
42func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
43	r, s = leaktoret22(q, p)
44	return r, s
45}
46
47func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
48	rr, ss := leaktoret22(q, p)
49	return rr, ss
50}
51
52var gp *int
53
54func leaktosink(p *int) *int { // ERROR "leaking param: p"
55	gp = p
56	return p
57}
58
59func f1() {
60	var x int
61	p := noleak(&x) // ERROR "&x does not escape"
62	_ = p
63}
64
65func f2() {
66	var x int
67	p := leaktoret(&x) // ERROR "&x does not escape"
68	_ = p
69}
70
71func f3() {
72	var x int          // ERROR "moved to heap: x"
73	p := leaktoret(&x) // ERROR "&x escapes to heap"
74	gp = p
75}
76
77func f4() {
78	var x int              // ERROR "moved to heap: x"
79	p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
80	gp = p
81	gp = q
82}
83
84func f5() {
85	var x int
86	leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
87}
88
89func f6() {
90	var x int                               // ERROR "moved to heap: x"
91	px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
92	gp = px1
93	_ = px2
94}
95
96type T struct{ x int }
97
98func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
99	t.x += u
100	return t, true
101}
102
103func f7() *T {
104	r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
105	return r
106}
107
108func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
109	return leakrecursive2(q, p)
110}
111
112func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
113	if *p > *q {
114		return leakrecursive1(q, p)
115	}
116	// without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
117	return p, q
118}
119
120
121var global interface{}
122
123type T1 struct {
124	X *int
125}
126
127type T2 struct {
128	Y *T1
129}
130
131func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
132	if p == nil {
133		k = T2{}
134		return
135	}
136
137	global = p // should make p leak always
138	return T2{p}
139}
140
141func f9() {
142	var j T1 // ERROR "moved to heap: j"
143	f8(&j) // ERROR "&j escapes to heap"
144}
145
146func f10() {
147	// These don't escape but are too big for the stack
148	var x [1<<30]byte // ERROR "moved to heap: x"
149	var y = make([]byte, 1<<30) // ERROR "does not escape"
150	_ = x[0] + y[0]
151}
152