diff options
Diffstat (limited to 'test/escape5.go')
-rw-r--r-- | test/escape5.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/test/escape5.go b/test/escape5.go new file mode 100644 index 000000000..6b327fe9e --- /dev/null +++ b/test/escape5.go @@ -0,0 +1,144 @@ +// 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" +} |