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.
7 // Test escape analysis for function parameters.
9 // In this test almost everything is BAD except the simplest cases
10 // where input directly flows to output.
14 func zero() int { return 0 }
19 func param0(p *int) *int { // ERROR "leaking param: p to result ~r0"
29 i := 0 // ERROR "moved to heap: i$"
34 func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r0" "leaking param: p2 to result ~r1"
39 i := 0 // ERROR "moved to heap: i$"
41 sink, _ = param1(&i, &j)
45 func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "p2 does not escape$"
50 i := 0 // ERROR "moved to heap: i$"
57 i := 0 // ERROR "moved to heap: i$"
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\]"
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]
73 type PairOfPairs struct {
77 type BoxedPair struct {
81 type WrappedPair struct {
85 func leakParam(x interface{}) { // ERROR "leaking param: x"
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"
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"
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)
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"
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)
114 func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape"
115 box1.pair.p1 = box2.pair.p1
118 func notSelfAssignment2(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
119 p1.pairs[0] = p2.pairs[1]
122 func notSelfAssignment3(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape"
123 p1.pairs[0].p1 = p2.pairs[1].p1
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"
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"
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"
153 i := 0 // ERROR "moved to heap: i$"
154 j := 0 // ERROR "moved to heap: j$"
157 sink = p // ERROR "p escapes to heap$"
161 func (p *Pair) param4(i *int) { // ERROR "p does not escape$" "leaking param: i$"
166 i := 0 // ERROR "moved to heap: i$"
173 i := 0 // ERROR "moved to heap: i$"
176 sink = p // ERROR "p escapes to heap$"
180 func param5(i *int) { // ERROR "leaking param: i$"
185 i := 0 // ERROR "moved to heap: i$"
190 func param6(i ***int) { // ERROR "leaking param content: i$"
195 i := 0 // ERROR "moved to heap: i$"
196 p := &i // ERROR "moved to heap: p$"
202 func param7(i ***int) { // ERROR "leaking param content: i$"
207 i := 0 // ERROR "moved to heap: i$"
214 func param8(i **int) { // ERROR "i does not escape$"
215 sink = **i // ERROR "\*\(\*i\) escapes to heap"
225 func param9(p ***int) **int { // ERROR "leaking param: p to result ~r0 level=1"
237 i := 0 // ERROR "moved to heap: i$"
238 p := &i // ERROR "moved to heap: p$"
244 func param10(p ***int) *int { // ERROR "leaking param: p to result ~r0 level=2"
256 i := 0 // ERROR "moved to heap: i$"
262 // in escapes to heap (address of param taken and returned)
263 func param11(i **int) ***int { // ERROR "moved to heap: i$"
268 i := 0 // ERROR "moved to heap: i"
269 p := &i // ERROR "moved to heap: p"
274 i := 0 // ERROR "moved to heap: i$"
275 p := &i // ERROR "moved to heap: p$"
279 func caller11c() { // GOOD
280 i := 0 // ERROR "moved to heap: i$"
281 p := &i // ERROR "moved to heap: p"
286 i := 0 // ERROR "moved to heap: i$"
287 p := &i // ERROR "moved to heap: p"
297 func (r *Indir) param12(i **int) { // ERROR "r does not escape$" "moved to heap: i$"
302 i := 0 // ERROR "moved to heap: i$"
303 p := &i // ERROR "moved to heap: p$"
310 i := 0 // ERROR "moved to heap: i$"
311 p := &i // ERROR "moved to heap: p$"
312 r := &Indir{} // ERROR "&Indir{} does not escape$"
318 i := 0 // ERROR "moved to heap: i$"
319 p := &i // ERROR "moved to heap: p$"
326 i := 0 // ERROR "moved to heap: i$"
327 p := &i // ERROR "moved to heap: p$"
338 func (v Val) param13(i *int) { // ERROR "v does not escape$" "leaking param: i$"
343 i := 0 // ERROR "moved to heap: i$"
352 i := 0 // ERROR "moved to heap: i$"
360 i := 0 // ERROR "moved to heap: i$"
362 v := &Val{&p} // ERROR "&Val{...} does not escape$"
368 i := 0 // ERROR "moved to heap: i$"
369 var p *int // ERROR "moved to heap: p$"
377 i := 0 // ERROR "moved to heap: i$"
378 var p *int // ERROR "moved to heap: p$"
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$"
393 i := 0 // ERROR "moved to heap: i$"
401 i := 0 // ERROR "moved to heap: i$"
403 v := &Val{&p} // ERROR "&Val{...} does not escape$"
405 sink = **v.p // ERROR "\*\(\*v\.p\) escapes to heap"
414 func f(x *Node) { // ERROR "leaking param content: x"
415 Sink = &Node{x.p} // ERROR "&Node{...} escapes to heap"
418 func g(x *Node) *Node { // ERROR "leaking param content: x"
419 return &Node{x.p} // ERROR "&Node{...} escapes to heap"
422 func h(x *Node) { // ERROR "leaking param: x"
423 y := &Node{x} // ERROR "&Node{...} does not escape"
428 // interface(in) -> out
429 // See also issue 29353.
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"
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"