1// errorcheck -0 -m -l
2
3// Copyright 2015 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 escape analysis for closure arguments.
8
9package escape
10
11var sink interface{}
12
13func ClosureCallArgs0() {
14	x := 0
15	func(p *int) { // ERROR "p does not escape" "func literal does not escape"
16		*p = 1
17	}(&x)
18}
19
20func ClosureCallArgs1() {
21	x := 0
22	for {
23		func(p *int) { // ERROR "p does not escape" "func literal does not escape"
24			*p = 1
25		}(&x)
26	}
27}
28
29func ClosureCallArgs2() {
30	for {
31		x := 0
32		func(p *int) { // ERROR "p does not escape" "func literal does not escape"
33			*p = 1
34		}(&x)
35	}
36}
37
38func ClosureCallArgs3() {
39	x := 0         // ERROR "moved to heap: x"
40	func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
41		sink = p
42	}(&x)
43}
44
45func ClosureCallArgs4() {
46	x := 0
47	_ = func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape"
48		return p
49	}(&x)
50}
51
52func ClosureCallArgs5() {
53	x := 0 // ERROR "moved to heap: x"
54	// TODO(mdempsky): We get "leaking param: p" here because the new escape analysis pass
55	// can tell that p flows directly to sink, but it's a little weird. Re-evaluate.
56	sink = func(p *int) *int { // ERROR "leaking param: p" "func literal does not escape"
57		return p
58	}(&x)
59}
60
61func ClosureCallArgs6() {
62	x := 0         // ERROR "moved to heap: x"
63	func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
64		sink = &p
65	}(&x)
66}
67
68func ClosureCallArgs7() {
69	var pp *int
70	for {
71		x := 0         // ERROR "moved to heap: x"
72		func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
73			pp = p
74		}(&x)
75	}
76	_ = pp
77}
78
79func ClosureCallArgs8() {
80	x := 0
81	defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
82		*p = 1
83	}(&x)
84}
85
86func ClosureCallArgs9() {
87	// BAD: x should not leak
88	x := 0 // ERROR "moved to heap: x"
89	for {
90		defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
91			*p = 1
92		}(&x)
93	}
94}
95
96func ClosureCallArgs10() {
97	for {
98		x := 0               // ERROR "moved to heap: x"
99		defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
100			*p = 1
101		}(&x)
102	}
103}
104
105func ClosureCallArgs11() {
106	x := 0               // ERROR "moved to heap: x"
107	defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
108		sink = p
109	}(&x)
110}
111
112func ClosureCallArgs12() {
113	x := 0
114	defer func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape"
115		return p
116	}(&x)
117}
118
119func ClosureCallArgs13() {
120	x := 0               // ERROR "moved to heap: x"
121	defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
122		sink = &p
123	}(&x)
124}
125
126func ClosureCallArgs14() {
127	x := 0
128	p := &x
129	_ = func(p **int) *int { // ERROR "leaking param: p to result ~r0 level=1" "func literal does not escape"
130		return *p
131	}(&p)
132}
133
134func ClosureCallArgs15() {
135	x := 0 // ERROR "moved to heap: x"
136	p := &x
137	sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape"
138		return *p
139	}(&p)
140}
141
142func ClosureLeak1(s string) string { // ERROR "s does not escape"
143	t := s + "YYYY"         // ERROR "escapes to heap"
144	return ClosureLeak1a(t) // ERROR "... argument does not escape"
145}
146
147// See #14409 -- returning part of captured var leaks it.
148func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r0 level=1$"
149	return func() string { // ERROR "func literal does not escape"
150		return a[0]
151	}()
152}
153
154func ClosureLeak2(s string) string { // ERROR "s does not escape"
155	t := s + "YYYY"       // ERROR "escapes to heap"
156	c := ClosureLeak2a(t) // ERROR "... argument does not escape"
157	return c
158}
159func ClosureLeak2a(a ...string) string { // ERROR "leaking param content: a"
160	return ClosureLeak2b(func() string { // ERROR "func literal does not escape"
161		return a[0]
162	})
163}
164func ClosureLeak2b(f func() string) string { // ERROR "f does not escape"
165	return f()
166}
167
168func ClosureIndirect() {
169	f := func(p *int) {} // ERROR "p does not escape" "func literal does not escape"
170	f(new(int))          // ERROR "new\(int\) does not escape"
171
172	g := f
173	g(new(int)) // ERROR "new\(int\) does not escape"
174
175	h := nopFunc
176	h(new(int)) // ERROR "new\(int\) does not escape"
177}
178
179func nopFunc(p *int) {} // ERROR "p does not escape"
180