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