| // 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 | |
| sink = x.p1 | |
| } | |
| func field1() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var x X | |
| // BAD: &i should not escape | |
| x.p1 = &i | |
| sink = x.p2 | |
| } | |
| func field3() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var x X | |
| x.p1 = &i | |
| sink = x // ERROR "x escapes to heap" | |
| } | |
| func field4() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var y Y | |
| y.x.p1 = &i | |
| x := y.x | |
| sink = x // ERROR "x escapes to heap" | |
| } | |
| func field5() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var x X | |
| // BAD: &i should not escape here | |
| x.a[0] = &i | |
| sink = x.a[1] | |
| } | |
| // BAD: we are not leaking param x, only x.p2 | |
| func field6(x *X) { // ERROR "leaking param content: x$" | |
| sink = x.p2 | |
| } | |
| func field6a() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var x X | |
| // BAD: &i should not escape | |
| x.p1 = &i | |
| field6(&x) | |
| } | |
| func field7() { | |
| i := 0 | |
| var y Y | |
| y.x.p1 = &i | |
| 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 | |
| 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 | |
| x := y.x | |
| var y1 Y | |
| y1.x = x | |
| sink = y1.x // ERROR "y1\.x escapes to heap" | |
| } | |
| func field10() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var y Y | |
| // BAD: &i should not escape | |
| y.x.p1 = &i | |
| 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} | |
| sink = x.p1 | |
| } | |
| func field12() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| // BAD: &i should not escape | |
| x := X{p1: &i} | |
| sink = x.p2 | |
| } | |
| func field13() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| x := &X{p1: &i} // ERROR "&X{...} 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 "&X{...} does not escape$" | |
| sink = x.p2 | |
| } | |
| func field15() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| x := &X{p1: &i} // ERROR "&X{...} 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 | |
| var iface interface{} = x // ERROR "x does not escape" | |
| x1 := iface.(X) | |
| sink = x1.p2 | |
| } | |
| func field17() { | |
| i := 0 // ERROR "moved to heap: i$" | |
| var x X | |
| x.p1 = &i | |
| var iface interface{} = x // ERROR "x does not escape" | |
| 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 | |
| var iface interface{} = x // ERROR "x does not escape" | |
| y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized. | |
| sink = y // ERROR "y escapes to heap" | |
| } |