github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/test/escape5.go (about) 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 10 package foo 11 12 func noleak(p *int) int { // ERROR "p does not escape" 13 return *p 14 } 15 16 func leaktoret(p *int) *int { // ERROR "leaking param: p to result" 17 return p 18 } 19 20 func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2" 21 return p, p 22 } 23 24 func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3" 25 return p, q 26 } 27 28 func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" 29 return leaktoret22(q, p) 30 } 31 32 func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" 33 r, s := leaktoret22(q, p) 34 return r, s 35 } 36 37 func 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 42 func 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 47 func 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 52 var gp *int 53 54 func leaktosink(p *int) *int { // ERROR "leaking param: p" 55 gp = p 56 return p 57 } 58 59 func f1() { 60 var x int 61 p := noleak(&x) // ERROR "&x does not escape" 62 _ = p 63 } 64 65 func f2() { 66 var x int 67 p := leaktoret(&x) // ERROR "&x does not escape" 68 _ = p 69 } 70 71 func f3() { 72 var x int // ERROR "moved to heap: x" 73 p := leaktoret(&x) // ERROR "&x escapes to heap" 74 gp = p 75 } 76 77 func 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 84 func f5() { 85 var x int 86 leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape" 87 } 88 89 func 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 96 type T struct{ x int } 97 98 func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result" 99 t.x += u 100 return t, true 101 } 102 103 func f7() *T { 104 r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap" 105 return r 106 } 107 108 func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" 109 return leakrecursive2(q, p) 110 } 111 112 func 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 var global interface{} 121 122 type T1 struct { 123 X *int 124 } 125 126 type T2 struct { 127 Y *T1 128 } 129 130 func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p" 131 if p == nil { 132 k = T2{} 133 return 134 } 135 136 // should make p leak always 137 global = p // ERROR "p escapes to heap" 138 return T2{p} 139 } 140 141 func f9() { 142 var j T1 // ERROR "moved to heap: j" 143 f8(&j) // ERROR "&j escapes to heap" 144 } 145 146 func 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 "make\(\[\]byte, 1 << 30\) escapes to heap" 150 _ = x[0] + y[0] 151 }