]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape_param.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / escape_param.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 function parameters.
8
9 // In this test almost everything is BAD except the simplest cases
10 // where input directly flows to output.
11
12 package escape
13
14 func zero() int { return 0 }
15
16 var sink interface{}
17
18 // in -> out
19 func param0(p *int) *int { // ERROR "leaking param: p to result ~r0"
20         return p
21 }
22
23 func caller0a() {
24         i := 0
25         _ = param0(&i)
26 }
27
28 func caller0b() {
29         i := 0 // ERROR "moved to heap: i$"
30         sink = param0(&i)
31 }
32
33 // in, in -> out, out
34 func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r0" "leaking param: p2 to result ~r1"
35         return p1, p2
36 }
37
38 func caller1() {
39         i := 0 // ERROR "moved to heap: i$"
40         j := 0
41         sink, _ = param1(&i, &j)
42 }
43
44 // in -> other in
45 func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "p2 does not escape$"
46         *p2 = p1
47 }
48
49 func caller2a() {
50         i := 0 // ERROR "moved to heap: i$"
51         var p *int
52         param2(&i, &p)
53         _ = p
54 }
55
56 func caller2b() {
57         i := 0 // ERROR "moved to heap: i$"
58         var p *int
59         param2(&i, &p)
60         sink = p
61 }
62
63 func paramArraySelfAssign(p *PairOfPairs) { // ERROR "p does not escape"
64         p.pairs[0] = p.pairs[1] // ERROR "ignoring self-assignment in p.pairs\[0\] = p.pairs\[1\]"
65 }
66
67 func paramArraySelfAssignUnsafeIndex(p *PairOfPairs) { // ERROR "leaking param content: p"
68         // Function call inside index disables self-assignment case to trigger.
69         p.pairs[zero()] = p.pairs[1]
70         p.pairs[zero()+1] = p.pairs[1]
71 }
72
73 type PairOfPairs struct {
74         pairs [2]*Pair
75 }
76
77 type BoxedPair struct {
78         pair *Pair
79 }
80
81 type WrappedPair struct {
82         pair Pair
83 }
84
85 func leakParam(x interface{}) { // ERROR "leaking param: x"
86         sink = x
87 }
88
89 func sinkAfterSelfAssignment1(box *BoxedPair) { // ERROR "leaking param content: box"
90         box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
91         sink = box.pair.p2
92 }
93
94 func sinkAfterSelfAssignment2(box *BoxedPair) { // ERROR "leaking param content: box"
95         box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
96         sink = box.pair
97 }
98
99 func sinkAfterSelfAssignment3(box *BoxedPair) { // ERROR "leaking param content: box"
100         box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
101         leakParam(box.pair.p2)
102 }
103
104 func sinkAfterSelfAssignment4(box *BoxedPair) { // ERROR "leaking param content: box"
105         box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
106         leakParam(box.pair)
107 }
108
109 func selfAssignmentAndUnrelated(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
110         box1.pair.p1 = box1.pair.p2 // ERROR "ignoring self-assignment in box1.pair.p1 = box1.pair.p2"
111         leakParam(box2.pair.p2)
112 }
113
114 func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
115         box1.pair.p1 = box2.pair.p1
116 }
117
118 func notSelfAssignment2(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
119         p1.pairs[0] = p2.pairs[1]
120 }
121
122 func notSelfAssignment3(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
123         p1.pairs[0].p1 = p2.pairs[1].p1
124 }
125
126 func boxedPairSelfAssign(box *BoxedPair) { // ERROR "box does not escape"
127         box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2"
128 }
129
130 func wrappedPairSelfAssign(w *WrappedPair) { // ERROR "w does not escape"
131         w.pair.p1 = w.pair.p2 // ERROR "ignoring self-assignment in w.pair.p1 = w.pair.p2"
132 }
133
134 // in -> in
135 type Pair struct {
136         p1 *int
137         p2 *int
138 }
139
140 func param3(p *Pair) { // ERROR "p does not escape"
141         p.p1 = p.p2 // ERROR "param3 ignoring self-assignment in p.p1 = p.p2"
142 }
143
144 func caller3a() {
145         i := 0
146         j := 0
147         p := Pair{&i, &j}
148         param3(&p)
149         _ = p
150 }
151
152 func caller3b() {
153         i := 0 // ERROR "moved to heap: i$"
154         j := 0 // ERROR "moved to heap: j$"
155         p := Pair{&i, &j}
156         param3(&p)
157         sink = p // ERROR "p escapes to heap$"
158 }
159
160 // in -> rcvr
161 func (p *Pair) param4(i *int) { // ERROR "p does not escape$" "leaking param: i$"
162         p.p1 = i
163 }
164
165 func caller4a() {
166         i := 0 // ERROR "moved to heap: i$"
167         p := Pair{}
168         p.param4(&i)
169         _ = p
170 }
171
172 func caller4b() {
173         i := 0 // ERROR "moved to heap: i$"
174         p := Pair{}
175         p.param4(&i)
176         sink = p // ERROR "p escapes to heap$"
177 }
178
179 // in -> heap
180 func param5(i *int) { // ERROR "leaking param: i$"
181         sink = i
182 }
183
184 func caller5() {
185         i := 0 // ERROR "moved to heap: i$"
186         param5(&i)
187 }
188
189 // *in -> heap
190 func param6(i ***int) { // ERROR "leaking param content: i$"
191         sink = *i
192 }
193
194 func caller6a() {
195         i := 0  // ERROR "moved to heap: i$"
196         p := &i // ERROR "moved to heap: p$"
197         p2 := &p
198         param6(&p2)
199 }
200
201 // **in -> heap
202 func param7(i ***int) { // ERROR "leaking param content: i$"
203         sink = **i
204 }
205
206 func caller7() {
207         i := 0 // ERROR "moved to heap: i$"
208         p := &i
209         p2 := &p
210         param7(&p2)
211 }
212
213 // **in -> heap
214 func param8(i **int) { // ERROR "i does not escape$"
215         sink = **i // ERROR "\*\(\*i\) escapes to heap"
216 }
217
218 func caller8() {
219         i := 0
220         p := &i
221         param8(&p)
222 }
223
224 // *in -> out
225 func param9(p ***int) **int { // ERROR "leaking param: p to result ~r0 level=1"
226         return *p
227 }
228
229 func caller9a() {
230         i := 0
231         p := &i
232         p2 := &p
233         _ = param9(&p2)
234 }
235
236 func caller9b() {
237         i := 0  // ERROR "moved to heap: i$"
238         p := &i // ERROR "moved to heap: p$"
239         p2 := &p
240         sink = param9(&p2)
241 }
242
243 // **in -> out
244 func param10(p ***int) *int { // ERROR "leaking param: p to result ~r0 level=2"
245         return **p
246 }
247
248 func caller10a() {
249         i := 0
250         p := &i
251         p2 := &p
252         _ = param10(&p2)
253 }
254
255 func caller10b() {
256         i := 0 // ERROR "moved to heap: i$"
257         p := &i
258         p2 := &p
259         sink = param10(&p2)
260 }
261
262 // in escapes to heap (address of param taken and returned)
263 func param11(i **int) ***int { // ERROR "moved to heap: i$"
264         return &i
265 }
266
267 func caller11a() {
268         i := 0  // ERROR "moved to heap: i"
269         p := &i // ERROR "moved to heap: p"
270         _ = param11(&p)
271 }
272
273 func caller11b() {
274         i := 0  // ERROR "moved to heap: i$"
275         p := &i // ERROR "moved to heap: p$"
276         sink = param11(&p)
277 }
278
279 func caller11c() { // GOOD
280         i := 0  // ERROR "moved to heap: i$"
281         p := &i // ERROR "moved to heap: p"
282         sink = *param11(&p)
283 }
284
285 func caller11d() {
286         i := 0  // ERROR "moved to heap: i$"
287         p := &i // ERROR "moved to heap: p"
288         p2 := &p
289         sink = param11(p2)
290 }
291
292 // &in -> rcvr
293 type Indir struct {
294         p ***int
295 }
296
297 func (r *Indir) param12(i **int) { // ERROR "r does not escape$" "moved to heap: i$"
298         r.p = &i
299 }
300
301 func caller12a() {
302         i := 0  // ERROR "moved to heap: i$"
303         p := &i // ERROR "moved to heap: p$"
304         var r Indir
305         r.param12(&p)
306         _ = r
307 }
308
309 func caller12b() {
310         i := 0        // ERROR "moved to heap: i$"
311         p := &i       // ERROR "moved to heap: p$"
312         r := &Indir{} // ERROR "&Indir{} does not escape$"
313         r.param12(&p)
314         _ = r
315 }
316
317 func caller12c() {
318         i := 0  // ERROR "moved to heap: i$"
319         p := &i // ERROR "moved to heap: p$"
320         r := Indir{}
321         r.param12(&p)
322         sink = r
323 }
324
325 func caller12d() {
326         i := 0  // ERROR "moved to heap: i$"
327         p := &i // ERROR "moved to heap: p$"
328         r := Indir{}
329         r.param12(&p)
330         sink = **r.p
331 }
332
333 // in -> value rcvr
334 type Val struct {
335         p **int
336 }
337
338 func (v Val) param13(i *int) { // ERROR "v does not escape$" "leaking param: i$"
339         *v.p = i
340 }
341
342 func caller13a() {
343         i := 0 // ERROR "moved to heap: i$"
344         var p *int
345         var v Val
346         v.p = &p
347         v.param13(&i)
348         _ = v
349 }
350
351 func caller13b() {
352         i := 0 // ERROR "moved to heap: i$"
353         var p *int
354         v := Val{&p}
355         v.param13(&i)
356         _ = v
357 }
358
359 func caller13c() {
360         i := 0 // ERROR "moved to heap: i$"
361         var p *int
362         v := &Val{&p} // ERROR "&Val{...} does not escape$"
363         v.param13(&i)
364         _ = v
365 }
366
367 func caller13d() {
368         i := 0     // ERROR "moved to heap: i$"
369         var p *int // ERROR "moved to heap: p$"
370         var v Val
371         v.p = &p
372         v.param13(&i)
373         sink = v
374 }
375
376 func caller13e() {
377         i := 0     // ERROR "moved to heap: i$"
378         var p *int // ERROR "moved to heap: p$"
379         v := Val{&p}
380         v.param13(&i)
381         sink = v
382 }
383
384 func caller13f() {
385         i := 0        // ERROR "moved to heap: i$"
386         var p *int    // ERROR "moved to heap: p$"
387         v := &Val{&p} // ERROR "&Val{...} escapes to heap$"
388         v.param13(&i)
389         sink = v
390 }
391
392 func caller13g() {
393         i := 0 // ERROR "moved to heap: i$"
394         var p *int
395         v := Val{&p}
396         v.param13(&i)
397         sink = *v.p
398 }
399
400 func caller13h() {
401         i := 0 // ERROR "moved to heap: i$"
402         var p *int
403         v := &Val{&p} // ERROR "&Val{...} does not escape$"
404         v.param13(&i)
405         sink = **v.p // ERROR "\*\(\*v\.p\) escapes to heap"
406 }
407
408 type Node struct {
409         p *Node
410 }
411
412 var Sink *Node
413
414 func f(x *Node) { // ERROR "leaking param content: x"
415         Sink = &Node{x.p} // ERROR "&Node{...} escapes to heap"
416 }
417
418 func g(x *Node) *Node { // ERROR "leaking param content: x"
419         return &Node{x.p} // ERROR "&Node{...} escapes to heap"
420 }
421
422 func h(x *Node) { // ERROR "leaking param: x"
423         y := &Node{x} // ERROR "&Node{...} does not escape"
424         Sink = g(y)
425         f(y)
426 }
427
428 // interface(in) -> out
429 // See also issue 29353.
430
431 // Convert to a non-direct interface, require an allocation and
432 // copy x to heap (not to result).
433 func param14a(x [4]*int) interface{} { // ERROR "leaking param: x$"
434         return x // ERROR "x escapes to heap"
435 }
436
437 // Convert to a direct interface, does not need an allocation.
438 // So x only leaks to result.
439 func param14b(x *int) interface{} { // ERROR "leaking param: x to result ~r0 level=0"
440         return x
441 }