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 10package foo 11 12import ( 13 "runtime" 14 "unsafe" 15) 16 17func noleak(p *int) int { // ERROR "p does not escape" 18 return *p 19} 20 21func leaktoret(p *int) *int { // ERROR "leaking param: p to result" 22 return p 23} 24 25func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2" 26 return p, p 27} 28 29func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3" 30 return p, q 31} 32 33func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" 34 return leaktoret22(q, p) 35} 36 37func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" 38 r, s := leaktoret22(q, p) 39 return r, s 40} 41 42func leaktoret22d(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 45} 46 47func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" 48 r, s = leaktoret22(q, p) 49 return r, s 50} 51 52func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" 53 rr, ss := leaktoret22(q, p) 54 return rr, ss 55} 56 57var gp *int 58 59func leaktosink(p *int) *int { // ERROR "leaking param: p" 60 gp = p 61 return p 62} 63 64func f1() { 65 var x int 66 p := noleak(&x) 67 _ = p 68} 69 70func f2() { 71 var x int 72 p := leaktoret(&x) 73 _ = p 74} 75 76func f3() { 77 var x int // ERROR "moved to heap: x" 78 p := leaktoret(&x) 79 gp = p 80} 81 82func f4() { 83 var x int // ERROR "moved to heap: x" 84 p, q := leaktoret2(&x) 85 gp = p 86 gp = q 87} 88 89func f5() { 90 var x int 91 leaktoret22(leaktoret2(&x)) 92} 93 94func f6() { 95 var x int // ERROR "moved to heap: x" 96 px1, px2 := leaktoret22(leaktoret2(&x)) 97 gp = px1 98 _ = px2 99} 100 101type T struct{ x int } 102 103func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result" 104 t.x += u 105 return t, true 106} 107 108func f7() *T { 109 r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap" 110 return r 111} 112 113func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" 114 return leakrecursive2(q, p) 115} 116 117func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" 118 if *p > *q { 119 return leakrecursive1(q, p) 120 } 121 // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges. 122 return p, q 123} 124 125var global interface{} 126 127type T1 struct { 128 X *int 129} 130 131type T2 struct { 132 Y *T1 133} 134 135func f8(p *T1) (k T2) { // ERROR "leaking param: p$" 136 if p == nil { 137 k = T2{} 138 return 139 } 140 141 // should make p leak always 142 global = p 143 return T2{p} 144} 145 146func f9() { 147 var j T1 // ERROR "moved to heap: j" 148 f8(&j) 149} 150 151func f10() { 152 // These don't escape but are too big for the stack 153 var x [1 << 30]byte // ERROR "moved to heap: x" 154 var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap" 155 _ = x[0] + y[0] 156} 157 158// Test for issue 19687 (passing to unnamed parameters does not escape). 159func f11(**int) { 160} 161func f12(_ **int) { 162} 163func f13() { 164 var x *int 165 f11(&x) 166 f12(&x) 167 runtime.KeepAlive(&x) 168} 169 170// Test for issue 24305 (passing to unnamed receivers does not escape). 171type U int 172 173func (*U) M() {} 174func (_ *U) N() {} 175 176func _() { 177 var u U 178 u.M() 179 u.N() 180} 181 182func fbad24305() { 183 // BAD u should not be heap allocated 184 var u U // ERROR "moved to heap: u" 185 (*U).M(&u) 186 (*U).N(&u) 187} 188 189// Issue 24730: taking address in a loop causes unnecessary escape 190type T24730 struct { 191 x [64]byte 192} 193 194func (t *T24730) g() { // ERROR "t does not escape" 195 y := t.x[:] 196 for i := range t.x[:] { 197 y = t.x[:] 198 y[i] = 1 199 } 200 201 var z *byte 202 for i := range t.x[:] { 203 z = &t.x[i] 204 *z = 2 205 } 206} 207 208// Issue 15730: copy causes unnecessary escape 209 210var sink []byte 211var sink2 []int 212var sink3 []*int 213 214func f15730a(args ...interface{}) { // ERROR "args does not escape" 215 for _, arg := range args { 216 switch a := arg.(type) { 217 case string: 218 copy(sink, a) 219 } 220 } 221} 222 223func f15730b(args ...interface{}) { // ERROR "args does not escape" 224 for _, arg := range args { 225 switch a := arg.(type) { 226 case []int: 227 copy(sink2, a) 228 } 229 } 230} 231 232func f15730c(args ...interface{}) { // ERROR "leaking param content: args" 233 for _, arg := range args { 234 switch a := arg.(type) { 235 case []*int: 236 // copy pointerful data should cause escape 237 copy(sink3, a) 238 } 239 } 240} 241 242// Issue 29000: unnamed parameter is not handled correctly 243 244var sink4 interface{} 245var alwaysFalse = false 246 247func f29000(_ int, x interface{}) { // ERROR "leaking param: x" 248 sink4 = x 249 if alwaysFalse { 250 g29000() 251 } 252} 253 254func g29000() { 255 x := 1 256 f29000(2, x) // ERROR "x escapes to heap" 257} 258 259// Issue 28369: taking an address of a parameter and converting it into a uintptr causes an 260// unnecessary escape. 261 262var sink28369 uintptr 263 264func f28369(n int) int { 265 if n == 0 { 266 sink28369 = uintptr(unsafe.Pointer(&n)) 267 return n 268 } 269 270 return 1 + f28369(n-1) 271} 272