// errorcheck -0 -m -l // Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Test, using compiler diagnostic flags, that the escape analysis is working. // Compiles but does not run. Inlining is disabled. package foo func noleak(p *int) int { // ERROR "p does not escape" return *p } func leaktoret(p *int) *int { // ERROR "leaking param: p to result" return p } func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result .anon1" "leaking param: p to result .anon2" return p, p } func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon2" "leaking param: q to result .anon3" return p, q } func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" return leaktoret22(q, p) } func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result .anon3" "leaking param: q to result .anon2" r, s := leaktoret22(q, p) return r, s } func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" r, s = leaktoret22(q, p) return } func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" r, s = leaktoret22(q, p) return r, s } func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" rr, ss := leaktoret22(q, p) return rr, ss } var gp *int func leaktosink(p *int) *int { // ERROR "leaking param: p" gp = p return p } func f1() { var x int p := noleak(&x) // ERROR "&x does not escape" _ = p } func f2() { var x int p := leaktoret(&x) // ERROR "&x does not escape" _ = p } func f3() { var x int // ERROR "moved to heap: x" p := leaktoret(&x) // ERROR "&x escapes to heap" gp = p } func f4() { var x int // ERROR "moved to heap: x" p, q := leaktoret2(&x) // ERROR "&x escapes to heap" gp = p gp = q } func f5() { var x int leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape" } func f6() { var x int // ERROR "moved to heap: x" px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap" gp = px1 _ = px2 } type T struct{ x int } func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result" t.x += u return t, true } func f7() *T { r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap" return r } func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" return leakrecursive2(q, p) } func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" if *p > *q { return leakrecursive1(q, p) } // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges. return p, q } var global interface{} type T1 struct { X *int } type T2 struct { Y *T1 } func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p" if p == nil { k = T2{} return } global = p // should make p leak always return T2{p} } func f9() { var j T1 // ERROR "moved to heap: j" f8(&j) // ERROR "&j escapes to heap" } func f10() { // These don't escape but are too big for the stack var x [1<<30]byte // ERROR "moved to heap: x" var y = make([]byte, 1<<30) // ERROR "does not escape" _ = x[0] + y[0] }