| // 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" |
| } |