]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape_closure.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / escape_closure.go
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
9 package escape
10
11 var sink interface{}
12
13 func 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
20 func 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
29 func 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
38 func 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
45 func 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
52 func 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
61 func 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
68 func 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
79 func 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
86 func 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
96 func 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
105 func 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
112 func 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
119 func 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
126 func 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
134 func 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
142 func 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.
148 func 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
154 func 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 }
159 func 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 }
164 func ClosureLeak2b(f func() string) string { // ERROR "f does not escape"
165         return f()
166 }
167
168 func 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
179 func nopFunc(p *int) {} // ERROR "p does not escape"
180
181 func ClosureIndirect2() {
182         f := func(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0" "func literal does not escape"
183
184         f(new(int)) // ERROR "new\(int\) does not escape"
185
186         g := f
187         g(new(int)) // ERROR "new\(int\) does not escape"
188
189         h := nopFunc2
190         h(new(int)) // ERROR "new\(int\) does not escape"
191 }
192
193 func nopFunc2(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0"