test: add escape analysis tests for fields
False positives (var incorrectly escapes) are marked with BAD.
Change-Id: I3027b6e0f5b48325e6169599400cc59e1394809f
Reviewed-on: https://go-review.googlesource.com/5431
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/test/escape_field.go b/test/escape_field.go
new file mode 100644
index 0000000..0ad1144
--- /dev/null
+++ b/test/escape_field.go
@@ -0,0 +1,175 @@
+// 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 with respect to field assignments.
+
+package escape
+
+var sink interface{}
+
+type X struct {
+ p1 *int
+ p2 *int
+ a [2]*int
+}
+
+type Y struct {
+ x X
+}
+
+func field0() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ sink = x.p1
+}
+
+func field1() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ sink = x.p2
+}
+
+func field3() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ sink = x
+}
+
+func field4() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i // ERROR "&i escapes to heap$"
+ x := y.x
+ sink = x
+}
+
+func field5() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape here
+ x.a[0] = &i // ERROR "&i escapes to heap$"
+ sink = x.a[1]
+}
+
+// BAD: we are not leaking param x, only x.p2
+func field6(x *X) { // ERROR "leaking param: x$"
+ sink = x.p2
+}
+
+func field6a() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X // ERROR "moved to heap: x$"
+ // BAD: &i should not escape
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ // BAD: &x should not escape
+ field6(&x) // ERROR "&x escapes to heap$"
+}
+
+func field7() {
+ i := 0
+ var y Y
+ y.x.p1 = &i // ERROR "field7 &i does not escape$"
+ x := y.x
+ var y1 Y
+ y1.x = x
+ _ = y1.x.p1
+}
+
+func field8() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i // ERROR "&i escapes to heap$"
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x.p1
+}
+
+func field9() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ y.x.p1 = &i // ERROR "&i escapes to heap$"
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x
+}
+
+func field10() {
+ i := 0 // ERROR "moved to heap: i$"
+ var y Y
+ // BAD: &i should not escape
+ y.x.p1 = &i // ERROR "&i escapes to heap$"
+ x := y.x
+ var y1 Y
+ y1.x = x
+ sink = y1.x.p2
+}
+
+func field11() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := X{p1: &i} // ERROR "&i escapes to heap$"
+ sink = x.p1
+}
+
+func field12() {
+ i := 0 // ERROR "moved to heap: i$"
+ // BAD: &i should not escape
+ x := X{p1: &i} // ERROR "&i escapes to heap$"
+ sink = x.p2
+}
+
+func field13() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := &X{p1: &i} // ERROR "&i escapes to heap$" "field13 &X literal does not escape$"
+ sink = x.p1
+}
+
+func field14() {
+ i := 0 // ERROR "moved to heap: i$"
+ // BAD: &i should not escape
+ x := &X{p1: &i} // ERROR "&i escapes to heap$" "field14 &X literal does not escape$"
+ sink = x.p2
+}
+
+func field15() {
+ i := 0 // ERROR "moved to heap: i$"
+ x := &X{p1: &i} // ERROR "&X literal escapes to heap$" "&i escapes to heap$"
+ sink = x
+}
+
+func field16() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ var iface interface{} = x
+ x1 := iface.(X)
+ sink = x1.p2
+}
+
+func field17() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ var iface interface{} = x
+ x1 := iface.(X)
+ sink = x1.p1
+}
+
+func field18() {
+ i := 0 // ERROR "moved to heap: i$"
+ var x X
+ // BAD: &i should not escape
+ x.p1 = &i // ERROR "&i escapes to heap$"
+ var iface interface{} = x
+ y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized.
+ sink = y
+}