aboutsummaryrefslogtreecommitdiff
path: root/test/escape_iface.go
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2015-09-15 13:49:18 -0700
committerDan Willemsen <dwillemsen@google.com>2015-09-15 13:51:48 -0700
commit6ff23253f8283d0c81c9db51c2d7803e086c93ad (patch)
treed70b53746897f5f6a71c19b7c062a079b4f54001 /test/escape_iface.go
parent1630e73131c3c8cc2a16baa2aefe3b9b82de658b (diff)
downloadlinux-x86-6ff23253f8283d0c81c9db51c2d7803e086c93ad.tar.gz
Change-Id: Ic39c72590cb0561132faefbca121c3782372b9bf
Diffstat (limited to 'test/escape_iface.go')
-rw-r--r--test/escape_iface.go227
1 files changed, 227 insertions, 0 deletions
diff --git a/test/escape_iface.go b/test/escape_iface.go
new file mode 100644
index 000000000..2b1144ad2
--- /dev/null
+++ b/test/escape_iface.go
@@ -0,0 +1,227 @@
+// errorcheck -0 -m -l
+
+// Copyright 2015 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 escape analysis for interface conversions.
+
+package escape
+
+var sink interface{}
+
+type M interface {
+ M()
+}
+
+func mescapes(m M) { // ERROR "leaking param: m"
+ sink = m // ERROR "m escapes to heap"
+}
+
+func mdoesnotescape(m M) { // ERROR "m does not escape"
+}
+
+// Tests for type stored directly in iface and with value receiver method.
+type M0 struct {
+ p *int
+}
+
+func (M0) M() {
+}
+
+func efaceEscape0() {
+ {
+ i := 0
+ v := M0{&i} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i} // ERROR "&i escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := M0{&i} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(M0)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i} // ERROR "&i escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(M0)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i} // ERROR "&i escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M0{&i} // ERROR "&i escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := M0{&i} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+// Tests for type stored indirectly in iface and with value receiver method.
+type M1 struct {
+ p *int
+ x int
+}
+
+func (M1) M() {
+}
+
+func efaceEscape1() {
+ {
+ i := 0
+ v := M1{&i, 0} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0} // ERROR "&i escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := M1{&i, 0} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(M1)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0} // ERROR "&i escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(M1)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0} // ERROR "&i escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := M1{&i, 0} // ERROR "&i escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := M1{&i, 0} // ERROR "&i does not escape"
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+// Tests for type stored directly in iface and with pointer receiver method.
+type M2 struct {
+ p *int
+}
+
+func (*M2) M() {
+}
+
+func efaceEscape2() {
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ _ = x
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ sink = x // ERROR "x escapes to heap"
+ }
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(*M2)
+ _ = v1
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ v1 := x.(*M2)
+ sink = v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v does not escape"
+ v1 := x.(*M2)
+ sink = *v1 // ERROR "v1 escapes to heap"
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v does not escape"
+ v1, ok := x.(*M2)
+ sink = *v1 // ERROR "v1 escapes to heap"
+ _ = ok
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ // BAD: v does not escape to heap here
+ var x M = v // ERROR "v escapes to heap"
+ x.M()
+ }
+ {
+ i := 0 // ERROR "moved to heap: i"
+ v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap"
+ var x M = v // ERROR "v escapes to heap"
+ mescapes(x)
+ }
+ {
+ i := 0
+ v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape"
+ var x M = v // ERROR "v does not escape"
+ mdoesnotescape(x)
+ }
+}
+
+type T1 struct {
+ p *int
+}
+
+type T2 struct {
+ T1 T1
+}
+
+func dotTypeEscape() *T2 { // #11931
+ var x interface{}
+ x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1 literal does not escape"
+ return &T2{
+ T1: *(x.(*T1)), // ERROR "&T2 literal escapes to heap"
+ }
+}