summaryrefslogtreecommitdiff
path: root/test/escape5.go
diff options
context:
space:
mode:
Diffstat (limited to 'test/escape5.go')
-rw-r--r--test/escape5.go144
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"
+}