// 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 when assigning to indirections. package escape var sink interface{} type ConstPtr struct { p *int c ConstPtr2 x **ConstPtr } type ConstPtr2 struct { p *int i int } func constptr0() { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" // BAD: i should not escape here x.p = &i // ERROR "&i escapes to heap" _ = x } func constptr01() *ConstPtr { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" x.p = &i // ERROR "&i escapes to heap" return x } func constptr02() ConstPtr { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" x.p = &i // ERROR "&i escapes to heap" return *x } func constptr03() **ConstPtr { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" "moved to heap: x" x.p = &i // ERROR "&i escapes to heap" return &x // ERROR "&x escapes to heap" } func constptr1() { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" x.p = &i // ERROR "&i escapes to heap" sink = x } func constptr2() { i := 0 // ERROR "moved to heap: i" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" x.p = &i // ERROR "&i escapes to heap" sink = *x } func constptr4() *ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" *p = *&ConstPtr{} // ERROR "&ConstPtr literal does not escape" return p } func constptr5() *ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" *p = *p1 return p } // BAD: p should not escape here func constptr6(p *ConstPtr) { // ERROR "leaking param: p" p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" *p1 = *p _ = p1 } func constptr7() **ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" "moved to heap: p" var tmp ConstPtr2 p1 := &tmp // ERROR "&tmp does not escape" p.c = *p1 return &p // ERROR "&p escapes to heap" } func constptr8() *ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" var tmp ConstPtr2 p.c = *&tmp // ERROR "&tmp does not escape" return p } func constptr9() ConstPtr { p := new(ConstPtr) // ERROR "new\(ConstPtr\) does not escape" var p1 ConstPtr2 i := 0 // ERROR "moved to heap: i" p1.p = &i // ERROR "&i escapes to heap" p.c = p1 return *p } func constptr10() ConstPtr { x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr literal escapes to heap" i := 0 // ERROR "moved to heap: i" var p *ConstPtr p = &ConstPtr{p: &i, x: &x} // ERROR "&i escapes to heap" "&x escapes to heap" "&ConstPtr literal does not escape" var pp **ConstPtr pp = &p // ERROR "&p does not escape" return **pp } func constptr11() *ConstPtr { i := 0 // ERROR "moved to heap: i" p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" p1.p = &i // ERROR "&i escapes to heap" *p = *p1 return p } func foo(p **int) { // ERROR "foo p does not escape" i := 0 // ERROR "moved to heap: i" y := p *y = &i // ERROR "&i escapes to heap" } func foo1(p *int) { // ERROR "p does not escape" i := 0 // ERROR "moved to heap: i" y := &p // ERROR "&p does not escape" *y = &i // ERROR "&i escapes to heap" } func foo2() { type Z struct { f **int } x := new(int) // ERROR "moved to heap: x" "new\(int\) escapes to heap" sink = &x // ERROR "&x escapes to heap" var z Z z.f = &x // ERROR "&x does not escape" p := z.f i := 0 // ERROR "moved to heap: i" *p = &i // ERROR "&i escapes to heap" }