diff options
author | Dan Willemsen <dwillemsen@google.com> | 2015-09-15 13:49:18 -0700 |
---|---|---|
committer | Dan Willemsen <dwillemsen@google.com> | 2015-09-15 13:51:48 -0700 |
commit | 6ff23253f8283d0c81c9db51c2d7803e086c93ad (patch) | |
tree | d70b53746897f5f6a71c19b7c062a079b4f54001 /test/escape2n.go | |
parent | 1630e73131c3c8cc2a16baa2aefe3b9b82de658b (diff) | |
download | linux-x86-6ff23253f8283d0c81c9db51c2d7803e086c93ad.tar.gz |
Update prebuilts to go 1.5.1android-n-preview-2android-n-preview-1brillo-m9-releasebrillo-m9-devbrillo-m8-releasebrillo-m8-devbrillo-m7-releasebrillo-m7-mr-devbrillo-m7-devbrillo-m10-releasebrillo-m10-dev
Change-Id: Ic39c72590cb0561132faefbca121c3782372b9bf
Diffstat (limited to 'test/escape2n.go')
-rw-r--r-- | test/escape2n.go | 1048 |
1 files changed, 692 insertions, 356 deletions
diff --git a/test/escape2n.go b/test/escape2n.go index 002a78ea5..c32877321 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -18,94 +18,94 @@ import ( var gxx *int -func foo1(x int) { // ERROR "moved to heap: x" - gxx = &x // ERROR "&x escapes to heap" +func foo1(x int) { // ERROR "moved to heap: x$" + gxx = &x // ERROR "&x escapes to heap$" } -func foo2(yy *int) { // ERROR "leaking param: yy" +func foo2(yy *int) { // ERROR "leaking param: yy$" gxx = yy } -func foo3(x int) *int { // ERROR "moved to heap: x" - return &x // ERROR "&x escapes to heap" +func foo3(x int) *int { // ERROR "moved to heap: x$" + return &x // ERROR "&x escapes to heap$" } type T *T -func foo3b(t T) { // ERROR "leaking param: t" +func foo3b(t T) { // ERROR "leaking param: t$" *t = t } // xx isn't going anywhere, so use of yy is ok -func foo4(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape" +func foo4(xx, yy *int) { // ERROR "foo4 xx does not escape$" "foo4 yy does not escape$" xx = yy } // xx isn't going anywhere, so taking address of yy is ok -func foo5(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape" - xx = &yy // ERROR "&yy does not escape" +func foo5(xx **int, yy *int) { // ERROR "foo5 xx does not escape$" "foo5 yy does not escape$" + xx = &yy // ERROR "foo5 &yy does not escape$" } -func foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: yy" +func foo6(xx **int, yy *int) { // ERROR "foo6 xx does not escape$" "leaking param: yy$" *xx = yy } -func foo7(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape" +func foo7(xx **int, yy *int) { // ERROR "foo7 xx does not escape$" "foo7 yy does not escape$" **xx = *yy } -func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape" +func foo8(xx, yy *int) int { // ERROR "foo8 xx does not escape$" "foo8 yy does not escape$" xx = yy return *xx } -func foo9(xx, yy *int) *int { // ERROR "leaking param: xx" "leaking param: yy" +func foo9(xx, yy *int) *int { // ERROR "leaking param: xx to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$" xx = yy return xx } -func foo10(xx, yy *int) { // ERROR "xx does not escape" "yy does not escape" +func foo10(xx, yy *int) { // ERROR "foo10 xx does not escape$" "foo10 yy does not escape$" *xx = *yy } func foo11() int { x, y := 0, 42 - xx := &x // ERROR "&x does not escape" - yy := &y // ERROR "&y does not escape" + xx := &x // ERROR "foo11 &x does not escape$" + yy := &y // ERROR "foo11 &y does not escape$" *xx = *yy return x } var xxx **int -func foo12(yyy **int) { // ERROR "leaking param: yyy" +func foo12(yyy **int) { // ERROR "leaking param: yyy$" xxx = yyy } // Must treat yyy as leaking because *yyy leaks, and the escape analysis // summaries in exported metadata do not distinguish these two cases. -func foo13(yyy **int) { // ERROR "leaking param: yyy" +func foo13(yyy **int) { // ERROR "leaking param content: yyy$" *xxx = *yyy } -func foo14(yyy **int) { // ERROR "yyy does not escape" +func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$" **xxx = **yyy } -func foo15(yy *int) { // ERROR "moved to heap: yy" - xxx = &yy // ERROR "&yy escapes to heap" +func foo15(yy *int) { // ERROR "moved to heap: yy$" + xxx = &yy // ERROR "&yy escapes to heap$" } -func foo16(yy *int) { // ERROR "leaking param: yy" +func foo16(yy *int) { // ERROR "leaking param: yy$" *xxx = yy } -func foo17(yy *int) { // ERROR "yy does not escape" +func foo17(yy *int) { // ERROR "foo17 yy does not escape$" **xxx = *yy } -func foo18(y int) { // ERROR "moved to heap: "y" - *xxx = &y // ERROR "&y escapes to heap" +func foo18(y int) { // ERROR "moved to heap: y$" + *xxx = &y // ERROR "&y escapes to heap$" } func foo19(y int) { @@ -118,52 +118,52 @@ type Bar struct { } func NewBar() *Bar { - return &Bar{42, nil} // ERROR "&Bar literal escapes to heap" + return &Bar{42, nil} // ERROR "&Bar literal escapes to heap$" } -func NewBarp(x *int) *Bar { // ERROR "leaking param: x" - return &Bar{42, x} // ERROR "&Bar literal escapes to heap" +func NewBarp(x *int) *Bar { // ERROR "leaking param: x to result ~r1 level=-1$" + return &Bar{42, x} // ERROR "&Bar literal escapes to heap$" } -func NewBarp2(x *int) *Bar { // ERROR "x does not escape" - return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap" +func NewBarp2(x *int) *Bar { // ERROR "NewBarp2 x does not escape$" + return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$" } -func (b *Bar) NoLeak() int { // ERROR "b does not escape" +func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$" return *(b.ii) } -func (b *Bar) Leak() *int { // ERROR "leaking param: b" - return &b.i // ERROR "&b.i escapes to heap" +func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$" + return &b.i // ERROR "&b.i escapes to heap$" } -func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param b content to result ~r0" +func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: b to result ~r0 level=1$" return b.ii } -func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b" +func (b Bar) AlsoLeak() *int { // ERROR "leaking param: b to result ~r0 level=0$" return b.ii } -func (b Bar) LeaksToo() *int { // ERROR "leaking param: b" - v := 0 // ERROR "moved to heap: v" - b.ii = &v // ERROR "&v escapes" +func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$" + v := 0 // ERROR "moved to heap: v$" + b.ii = &v // ERROR "&v escapes to heap$" return b.ii } -func (b *Bar) LeaksABit() *int { // ERROR "leaking param b content to result ~r0" - v := 0 // ERROR "moved to heap: v" - b.ii = &v // ERROR "&v escapes" +func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$" + v := 0 // ERROR "moved to heap: v$" + b.ii = &v // ERROR "&v escapes to heap$" return b.ii } -func (b Bar) StillNoLeak() int { // ERROR "b does not escape" +func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$" v := 0 - b.ii = &v // ERROR "&v does not escape" + b.ii = &v // ERROR "Bar.StillNoLeak &v does not escape$" return b.i } -func goLeak(b *Bar) { // ERROR "leaking param: b" +func goLeak(b *Bar) { // ERROR "leaking param: b$" go b.NoLeak() } @@ -173,90 +173,105 @@ type Bar2 struct { } func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap" + return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$" } -func (b *Bar2) NoLeak() int { // ERROR "b does not escape" +func (b *Bar2) NoLeak() int { // ERROR "\(\*Bar2\).NoLeak b does not escape$" return b.i[0] } -func (b *Bar2) Leak() []int { // ERROR "leaking param: b" - return b.i[:] // ERROR "b.i escapes to heap" +func (b *Bar2) Leak() []int { // ERROR "leaking param: b to result ~r0 level=0$" + return b.i[:] // ERROR "b.i escapes to heap$" } -func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param b content to result ~r0" +func (b *Bar2) AlsoNoLeak() []int { // ERROR "leaking param: b to result ~r0 level=1$" return b.ii[0:1] } -func (b Bar2) AgainNoLeak() [12]int { // ERROR "b does not escape" +func (b Bar2) AgainNoLeak() [12]int { // ERROR "Bar2.AgainNoLeak b does not escape$" return b.i } -func (b *Bar2) LeakSelf() { // ERROR "leaking param: b" - b.ii = b.i[0:4] // ERROR "b.i escapes to heap" +func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$" + b.ii = b.i[0:4] // ERROR "b.i escapes to heap$" } -func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b" +func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$" var buf []int - buf = b.i[0:] // ERROR "b.i escapes to heap" + buf = b.i[0:] // ERROR "b.i escapes to heap$" b.ii = buf } func foo21() func() int { - x := 42 // ERROR "moved to heap: x" - return func() int { // ERROR "func literal escapes to heap" - return x // ERROR "&x escapes to heap" + x := 42 + return func() int { // ERROR "func literal escapes to heap$" + return x + } +} + +func foo21a() func() int { + x := 42 // ERROR "moved to heap: x$" + return func() int { // ERROR "func literal escapes to heap$" + x++ // ERROR "&x escapes to heap$" + return x } } func foo22() int { x := 42 - return func() int { // ERROR "func literal does not escape" + return func() int { // ERROR "foo22 func literal does not escape$" return x }() } -func foo23(x int) func() int { // ERROR "moved to heap: x" - return func() int { // ERROR "func literal escapes to heap" - return x // ERROR "&x escapes to heap" +func foo23(x int) func() int { + return func() int { // ERROR "func literal escapes to heap$" + return x } } -func foo23a(x int) func() int { // ERROR "moved to heap: x" - f := func() int { // ERROR "func literal escapes to heap" - return x // ERROR "&x escapes to heap" +func foo23a(x int) func() int { + f := func() int { // ERROR "func literal escapes to heap$" + return x } return f } -func foo23b(x int) *(func() int) { // ERROR "moved to heap: x" - f := func() int { return x } // ERROR "moved to heap: f" "func literal escapes to heap" "&x escapes to heap" - return &f // ERROR "&f escapes to heap" +func foo23b(x int) *(func() int) { + f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$" + return &f // ERROR "&f escapes to heap$" +} + +func foo23c(x int) func() int { // ERROR "moved to heap: x$" + return func() int { // ERROR "func literal escapes to heap$" + x++ // ERROR "&x escapes to heap$" + return x + } } func foo24(x int) int { - return func() int { // ERROR "func literal does not escape" + return func() int { // ERROR "foo24 func literal does not escape$" return x }() } var x *int -func fooleak(xx *int) int { // ERROR "leaking param: xx" +func fooleak(xx *int) int { // ERROR "leaking param: xx$" x = xx return *x } -func foonoleak(xx *int) int { // ERROR "xx does not escape" +func foonoleak(xx *int) int { // ERROR "foonoleak xx does not escape$" return *x + *xx } -func foo31(x int) int { // ERROR "moved to heap: x" - return fooleak(&x) // ERROR "&x escapes to heap" +func foo31(x int) int { // ERROR "moved to heap: x$" + return fooleak(&x) // ERROR "&x escapes to heap$" } func foo32(x int) int { - return foonoleak(&x) // ERROR "&x does not escape" + return foonoleak(&x) // ERROR "foo32 &x does not escape$" } type Foo struct { @@ -267,114 +282,114 @@ type Foo struct { var F Foo var pf *Foo -func (f *Foo) fooleak() { // ERROR "leaking param: f" +func (f *Foo) fooleak() { // ERROR "leaking param: f$" pf = f } -func (f *Foo) foonoleak() { // ERROR "f does not escape" +func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$" F.x = f.x } -func (f *Foo) Leak() { // ERROR "leaking param: f" +func (f *Foo) Leak() { // ERROR "leaking param: f$" f.fooleak() } -func (f *Foo) NoLeak() { // ERROR "f does not escape" +func (f *Foo) NoLeak() { // ERROR "\(\*Foo\).NoLeak f does not escape$" f.foonoleak() } -func foo41(x int) { // ERROR "moved to heap: x" - F.xx = &x // ERROR "&x escapes to heap" +func foo41(x int) { // ERROR "moved to heap: x$" + F.xx = &x // ERROR "&x escapes to heap$" } -func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: x" - f.xx = &x // ERROR "&x escapes to heap" +func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$" + f.xx = &x // ERROR "&x escapes to heap$" } -func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: x" - f.xx = &x // ERROR "&x escapes to heap" +func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$" + f.xx = &x // ERROR "&x escapes to heap$" } -func foo44(yy *int) { // ERROR "leaking param: yy" +func foo44(yy *int) { // ERROR "leaking param: yy$" F.xx = yy } -func (f *Foo) foo45() { // ERROR "f does not escape" +func (f *Foo) foo45() { // ERROR "\(\*Foo\).foo45 f does not escape$" F.x = f.x } // See foo13 above for explanation of why f leaks. -func (f *Foo) foo46() { // ERROR "leaking param: f" +func (f *Foo) foo46() { // ERROR "leaking param content: f$" F.xx = f.xx } -func (f *Foo) foo47() { // ERROR "leaking param: f" - f.xx = &f.x // ERROR "&f.x escapes to heap" +func (f *Foo) foo47() { // ERROR "leaking param: f$" + f.xx = &f.x // ERROR "&f.x escapes to heap$" } var ptrSlice []*int -func foo50(i *int) { // ERROR "leaking param: i" +func foo50(i *int) { // ERROR "leaking param: i$" ptrSlice[0] = i } var ptrMap map[*int]*int -func foo51(i *int) { // ERROR "leaking param: i" +func foo51(i *int) { // ERROR "leaking param: i$" ptrMap[i] = i } -func indaddr1(x int) *int { // ERROR "moved to heap: x" - return &x // ERROR "&x escapes to heap" +func indaddr1(x int) *int { // ERROR "moved to heap: x$" + return &x // ERROR "&x escapes to heap$" } -func indaddr2(x *int) *int { // ERROR "leaking param: x" - return *&x // ERROR "&x does not escape" +func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" + return *&x // ERROR "indaddr2 &x does not escape$" } -func indaddr3(x *int32) *int { // ERROR "leaking param: x" - return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape" +func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$" + return *(**int)(unsafe.Pointer(&x)) // ERROR "indaddr3 &x does not escape$" } // From package math: func Float32bits(f float32) uint32 { - return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape" + return *(*uint32)(unsafe.Pointer(&f)) // ERROR "Float32bits &f does not escape$" } func Float32frombits(b uint32) float32 { - return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape" + return *(*float32)(unsafe.Pointer(&b)) // ERROR "Float32frombits &b does not escape$" } func Float64bits(f float64) uint64 { - return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape" + return *(*uint64)(unsafe.Pointer(&f)) // ERROR "Float64bits &f does not escape$" } func Float64frombits(b uint64) float64 { - return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape" + return *(*float64)(unsafe.Pointer(&b)) // ERROR "Float64frombits &b does not escape$" } // contrast with -func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f" - return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap" +func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$" + return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap$" } -func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f" +func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: f to result ~r1 level=0$" return (*uint64)(unsafe.Pointer(f)) } -func typesw(i interface{}) *int { // ERROR "leaking param: i" +func typesw(i interface{}) *int { // ERROR "leaking param: i to result ~r1 level=0$" switch val := i.(type) { case *int: return val case *int8: - v := int(*val) // ERROR "moved to heap: v" - return &v // ERROR "&v escapes to heap" + v := int(*val) // ERROR "moved to heap: v$" + return &v // ERROR "&v escapes to heap$" } return nil } -func exprsw(i *int) *int { // ERROR "leaking param: i" +func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" switch j := i; *j + 110 { case 12: return j @@ -386,20 +401,20 @@ func exprsw(i *int) *int { // ERROR "leaking param: i" } // assigning to an array element is like assigning to the array -func foo60(i *int) *int { // ERROR "leaking param: i" +func foo60(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" var a [12]*int a[0] = i return a[1] } -func foo60a(i *int) *int { // ERROR "i does not escape" +func foo60a(i *int) *int { // ERROR "foo60a i does not escape$" var a [12]*int a[0] = i return nil } // assigning to a struct field is like assigning to the struct -func foo61(i *int) *int { // ERROR "leaking param: i" +func foo61(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" type S struct { a, b *int } @@ -408,7 +423,7 @@ func foo61(i *int) *int { // ERROR "leaking param: i" return s.b } -func foo61a(i *int) *int { // ERROR "i does not escape" +func foo61a(i *int) *int { // ERROR "foo61a i does not escape$" type S struct { a, b *int } @@ -420,11 +435,11 @@ func foo61a(i *int) *int { // ERROR "i does not escape" // assigning to a struct field is like assigning to the struct but // here this subtlety is lost, since s.a counts as an assignment to a // track-losing dereference. -func foo62(i *int) *int { // ERROR "leaking param: i" +func foo62(i *int) *int { // ERROR "leaking param: i$" type S struct { a, b *int } - s := new(S) // ERROR "new[(]S[)] does not escape" + s := new(S) // ERROR "foo62 new\(S\) does not escape$" s.a = i return nil // s.b } @@ -433,14 +448,14 @@ type M interface { M() } -func foo63(m M) { // ERROR "m does not escape" +func foo63(m M) { // ERROR "foo63 m does not escape$" } -func foo64(m M) { // ERROR "leaking param: m" +func foo64(m M) { // ERROR "leaking param: m$" m.M() } -func foo64b(m M) { // ERROR "leaking param: m" +func foo64b(m M) { // ERROR "leaking param: m$" defer m.M() } @@ -450,55 +465,56 @@ func (MV) M() {} func foo65() { var mv MV - foo63(&mv) // ERROR "&mv does not escape" + foo63(&mv) // ERROR "foo65 &mv does not escape$" } func foo66() { - var mv MV // ERROR "moved to heap: mv" - foo64(&mv) // ERROR "&mv escapes to heap" + var mv MV // ERROR "moved to heap: mv$" + foo64(&mv) // ERROR "&mv escapes to heap$" } func foo67() { var mv MV - foo63(mv) + foo63(mv) // ERROR "foo67 mv does not escape$" } func foo68() { var mv MV - foo64(mv) // escapes but it's an int so irrelevant + // escapes but it's an int so irrelevant + foo64(mv) // ERROR "mv escapes to heap$" } -func foo69(m M) { // ERROR "leaking param: m" +func foo69(m M) { // ERROR "leaking param: m$" foo64(m) } -func foo70(mv1 *MV, m M) { // ERROR "leaking param: mv1" "leaking param: m" - m = mv1 +func foo70(mv1 *MV, m M) { // ERROR "leaking param: m$" "leaking param: mv1$" + m = mv1 // ERROR "mv1 escapes to heap$" foo64(m) } -func foo71(x *int) []*int { // ERROR "leaking param: x" +func foo71(x *int) []*int { // ERROR "leaking param: x$" var y []*int y = append(y, x) return y } -func foo71a(x int) []*int { // ERROR "moved to heap: x" +func foo71a(x int) []*int { // ERROR "moved to heap: x$" var y []*int - y = append(y, &x) // ERROR "&x escapes to heap" + y = append(y, &x) // ERROR "&x escapes to heap$" return y } func foo72() { var x int var y [1]*int - y[0] = &x // ERROR "&x does not escape" + y[0] = &x // ERROR "foo72 &x does not escape$" } func foo72aa() [10]*int { - var x int // ERROR "moved to heap: x" + var x int // ERROR "moved to heap: x$" var y [10]*int - y[0] = &x // ERROR "&x escapes to heap" + y[0] = &x // ERROR "&x escapes to heap$" return y } @@ -506,8 +522,8 @@ func foo72a() { var y [10]*int for i := 0; i < 10; i++ { // escapes its scope - x := i // ERROR "moved to heap: x" - y[i] = &x // ERROR "&x escapes to heap" + x := i // ERROR "moved to heap: x$" + y[i] = &x // ERROR "&x escapes to heap$" } return } @@ -515,31 +531,56 @@ func foo72a() { func foo72b() [10]*int { var y [10]*int for i := 0; i < 10; i++ { - x := i // ERROR "moved to heap: x" - y[i] = &x // ERROR "&x escapes to heap" + x := i // ERROR "moved to heap: x$" + y[i] = &x // ERROR "&x escapes to heap$" } return y } // issue 2145 func foo73() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + s := []int{3, 2, 1} // ERROR "foo73 \[\]int literal does not escape$" + for _, v := range s { + vv := v + // actually just escapes its scope + defer func() { // ERROR "func literal escapes to heap$" + println(vv) + }() + } +} + +func foo731() { + s := []int{3, 2, 1} // ERROR "foo731 \[\]int literal does not escape$" for _, v := range s { - vv := v // ERROR "moved to heap: vv" + vv := v // ERROR "moved to heap: vv$" // actually just escapes its scope - defer func() { // ERROR "func literal escapes to heap" - println(vv) // ERROR "&vv escapes to heap" + defer func() { // ERROR "func literal escapes to heap$" + vv = 42 // ERROR "&vv escapes to heap$" + println(vv) }() } } func foo74() { - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$" for _, v := range s { - vv := v // ERROR "moved to heap: vv" + vv := v // actually just escapes its scope - fn := func() { // ERROR "func literal escapes to heap" - println(vv) // ERROR "&vv escapes to heap" + fn := func() { // ERROR "func literal escapes to heap$" + println(vv) + } + defer fn() + } +} + +func foo74a() { + s := []int{3, 2, 1} // ERROR "foo74a \[\]int literal does not escape$" + for _, v := range s { + vv := v // ERROR "moved to heap: vv$" + // actually just escapes its scope + fn := func() { // ERROR "func literal escapes to heap$" + vv += 1 // ERROR "&vv escapes to heap$" + println(vv) } defer fn() } @@ -548,110 +589,142 @@ func foo74() { // issue 3975 func foo74b() { var array [3]func() - s := []int{3, 2, 1} // ERROR "\[\]int literal does not escape" + s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$" for i, v := range s { - vv := v // ERROR "moved to heap: vv" + vv := v // actually just escapes its scope - array[i] = func() { // ERROR "func literal escapes to heap" - println(vv) // ERROR "&vv escapes to heap" + array[i] = func() { // ERROR "func literal escapes to heap$" + println(vv) } } } -func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: y" +func foo74c() { + var array [3]func() + s := []int{3, 2, 1} // ERROR "foo74c \[\]int literal does not escape$" + for i, v := range s { + vv := v // ERROR "moved to heap: vv$" + // actually just escapes its scope + array[i] = func() { // ERROR "func literal escapes to heap$" + println(&vv) // ERROR "&vv escapes to heap$" "foo74c.func1 &vv does not escape$" + } + } +} + +func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: y to result ~r2 level=0$" "myprint x does not escape$" return y } -func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: x" - return &x[0] // ERROR "&x.0. escapes to heap" +func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$" + return &x[0] // ERROR "&x\[0\] escapes to heap$" } -func foo75(z *int) { // ERROR "z does not escape" - myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +func foo75(z *int) { // ERROR "foo75 z does not escape$" + myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75 ... argument does not escape$" } -func foo75a(z *int) { // ERROR "z does not escape" - myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +func foo75a(z *int) { // ERROR "foo75a z does not escape$" + myprint1(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75a ... argument does not escape$" } -func foo75esc(z *int) { // ERROR "leaking param: z" - gxx = myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" +func foo75esc(z *int) { // ERROR "leaking param: z$" + gxx = myprint(z, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo75esc ... argument does not escape$" } -func foo75aesc(z *int) { // ERROR "z does not escape" +func foo75aesc(z *int) { // ERROR "foo75aesc z does not escape$" var ppi **interface{} // assignments to pointer dereferences lose track - *ppi = myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + *ppi = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" +} + +func foo75aesc1(z *int) { // ERROR "foo75aesc1 z does not escape$" + sink = myprint1(z, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "myprint1\(z, 1, 2, 3\) escapes to heap$" } -func foo76(z *int) { // ERROR "leaking param: z" - myprint(nil, z) // ERROR "[.][.][.] argument does not escape" +// BAD: z does not escape here +func foo76(z *int) { // ERROR "leaking param: z$" + myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z escapes to heap$" } -func foo76a(z *int) { // ERROR "leaking param: z" - myprint1(nil, z) // ERROR "[.][.][.] argument does not escape" +// BAD: z does not escape here +func foo76a(z *int) { // ERROR "leaking param: z$" + myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z escapes to heap$" } func foo76b() { - myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" + myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76b ... argument does not escape$" } func foo76c() { - myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" + myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76c ... argument does not escape$" } func foo76d() { - defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" + defer myprint(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76d ... argument does not escape$" } func foo76e() { - defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape" + defer myprint1(nil, 1, 2, 3) // ERROR "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" "foo76e ... argument does not escape$" } func foo76f() { for { // TODO: This one really only escapes its scope, but we don't distinguish yet. - defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + defer myprint(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } func foo76g() { for { - defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + defer myprint1(nil, 1, 2, 3) // ERROR "... argument escapes to heap$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" } } -func foo77(z []interface{}) { // ERROR "z does not escape" +func foo77(z []interface{}) { // ERROR "foo77 z does not escape$" myprint(nil, z...) // z does not escape } -func foo77a(z []interface{}) { // ERROR "z does not escape" +func foo77a(z []interface{}) { // ERROR "foo77a z does not escape$" myprint1(nil, z...) } -func foo77b(z []interface{}) { // ERROR "leaking param: z" +func foo77b(z []interface{}) { // ERROR "leaking param: z$" var ppi **interface{} *ppi = myprint1(nil, z...) } -func foo78(z int) *int { // ERROR "moved to heap: z" - return &z // ERROR "&z escapes to heap" +func foo77c(z []interface{}) { // ERROR "leaking param: z$" + sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$" } -func foo78a(z int) *int { // ERROR "moved to heap: z" - y := &z // ERROR "&z escapes to heap" - x := &y // ERROR "&y does not escape" +func dotdotdot() { + // BAD: i should not escape here + i := 0 // ERROR "moved to heap: i$" + myprint(nil, &i) // ERROR "&i escapes to heap$" "dotdotdot ... argument does not escape$" + + // BAD: j should not escape here + j := 0 // ERROR "moved to heap: j$" + myprint1(nil, &j) // ERROR "&j escapes to heap$" "dotdotdot ... argument does not escape$" +} + +func foo78(z int) *int { // ERROR "moved to heap: z$" + return &z // ERROR "&z escapes to heap$" +} + +func foo78a(z int) *int { // ERROR "moved to heap: z$" + y := &z // ERROR "&z escapes to heap$" + x := &y // ERROR "foo78a &y does not escape$" return *x // really return y } func foo79() *int { - return new(int) // ERROR "new[(]int[)] escapes to heap" + return new(int) // ERROR "new\(int\) escapes to heap$" } func foo80() *int { var z *int for { // Really just escapes its scope but we don't distinguish - z = new(int) // ERROR "new[(]int[)] escapes to heap" + z = new(int) // ERROR "new\(int\) escapes to heap$" } _ = z return nil @@ -659,24 +732,24 @@ func foo80() *int { func foo81() *int { for { - z := new(int) // ERROR "new[(]int[)] does not escape" + z := new(int) // ERROR "foo81 new\(int\) does not escape$" _ = z } return nil } -func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param" +func tee(p *int) (x, y *int) { return p, p } // ERROR "leaking param: p to result x level=0$" "leaking param: p to result y level=0$" -func noop(x, y *int) {} // ERROR "does not escape" +func noop(x, y *int) {} // ERROR "noop x does not escape$" "noop y does not escape$" func foo82() { - var x, y, z int // ERROR "moved to heap" - go noop(tee(&z)) // ERROR "&z escapes to heap" - go noop(&x, &y) // ERROR "escapes to heap" + var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$" + go noop(tee(&z)) // ERROR "&z escapes to heap$" + go noop(&x, &y) // ERROR "&x escapes to heap$" "&y escapes to heap$" for { - var u, v, w int // ERROR "moved to heap" - defer noop(tee(&u)) // ERROR "&u escapes to heap" - defer noop(&v, &w) // ERROR "escapes to heap" + var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$" + defer noop(tee(&u)) // ERROR "&u escapes to heap$" + defer noop(&v, &w) // ERROR "&v escapes to heap$" "&w escapes to heap$" } } @@ -689,24 +762,24 @@ type LimitedFooer struct { N int64 } -func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r" - return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap" +func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: r to result ~r2 level=-1$" + return &LimitedFooer{r, n} // ERROR "&LimitedFooer literal escapes to heap$" } -func foo90(x *int) map[*int]*int { // ERROR "leaking param: x" - return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap" +func foo90(x *int) map[*int]*int { // ERROR "leaking param: x$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" } -func foo91(x *int) map[*int]*int { // ERROR "leaking param: x" - return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap" +func foo91(x *int) map[*int]*int { // ERROR "leaking param: x$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" } -func foo92(x *int) [2]*int { // ERROR "leaking param: x" +func foo92(x *int) [2]*int { // ERROR "leaking param: x to result ~r1 level=0$" return [2]*int{x, nil} } // does not leak c -func foo93(c chan *int) *int { // ERROR "c does not escape" +func foo93(c chan *int) *int { // ERROR "foo93 c does not escape$" for v := range c { return v } @@ -714,7 +787,7 @@ func foo93(c chan *int) *int { // ERROR "c does not escape" } // does not leak m -func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape" +func foo94(m map[*int]*int, b bool) *int { // ERROR "leaking param: m to result ~r2 level=1" for k, v := range m { if b { return k @@ -725,32 +798,32 @@ func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape" } // does leak x -func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: x" +func foo95(m map[*int]*int, x *int) { // ERROR "foo95 m does not escape$" "leaking param: x$" m[x] = x } -// does not leak m -func foo96(m []*int) *int { // ERROR "m does not escape" +// does not leak m but does leak content +func foo96(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" return m[0] } // does leak m -func foo97(m [1]*int) *int { // ERROR "leaking param: m" +func foo97(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" return m[0] } // does not leak m -func foo98(m map[int]*int) *int { // ERROR "m does not escape" +func foo98(m map[int]*int) *int { // ERROR "foo98 m does not escape$" return m[0] } // does leak m -func foo99(m *[1]*int) []*int { // ERROR "leaking param: m" +func foo99(m *[1]*int) []*int { // ERROR "leaking param: m to result ~r1 level=0$" return m[:] } // does not leak m -func foo100(m []*int) *int { // ERROR "m does not escape" +func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" for _, v := range m { return v } @@ -758,7 +831,7 @@ func foo100(m []*int) *int { // ERROR "m does not escape" } // does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: m" +func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" for _, v := range m { return v } @@ -766,109 +839,109 @@ func foo101(m [1]*int) *int { // ERROR "leaking param: m" } // does not leak m -func foo101a(m [1]*int) *int { // ERROR "m does not escape" - for i := range m { // ERROR "moved to heap: i" - return &i // ERROR "&i escapes to heap" +func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$" + for i := range m { // ERROR "moved to heap: i$" + return &i // ERROR "&i escapes to heap$" } return nil } // does leak x -func foo102(m []*int, x *int) { // ERROR "m does not escape" "leaking param: x" +func foo102(m []*int, x *int) { // ERROR "foo102 m does not escape$" "leaking param: x$" m[0] = x } // does not leak x -func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape" +func foo103(m [1]*int, x *int) { // ERROR "foo103 m does not escape$" "foo103 x does not escape$" m[0] = x } var y []*int -// does not leak x -func foo104(x []*int) { // ERROR "x does not escape" +// does not leak x but does leak content +func foo104(x []*int) { // ERROR "leaking param content: x" copy(y, x) } -// does not leak x -func foo105(x []*int) { // ERROR "x does not escape" +// does not leak x but does leak content +func foo105(x []*int) { // ERROR "leaking param content: x" _ = append(y, x...) } // does leak x -func foo106(x *int) { // ERROR "leaking param: x" +func foo106(x *int) { // ERROR "leaking param: x$" _ = append(y, x) } -func foo107(x *int) map[*int]*int { // ERROR "leaking param: x" - return map[*int]*int{x: nil} // ERROR "map.* literal escapes to heap" +func foo107(x *int) map[*int]*int { // ERROR "leaking param: x$" + return map[*int]*int{x: nil} // ERROR "map\[\*int\]\*int literal escapes to heap$" } -func foo108(x *int) map[*int]*int { // ERROR "leaking param: x" - return map[*int]*int{nil: x} // ERROR "map.* literal escapes to heap" +func foo108(x *int) map[*int]*int { // ERROR "leaking param: x$" + return map[*int]*int{nil: x} // ERROR "map\[\*int\]\*int literal escapes to heap$" } -func foo109(x *int) *int { // ERROR "leaking param: x" - m := map[*int]*int{x: nil} // ERROR "map.* literal does not escape" +func foo109(x *int) *int { // ERROR "leaking param: x$" + m := map[*int]*int{x: nil} // ERROR "foo109 map\[\*int\]\*int literal does not escape$" for k, _ := range m { return k } return nil } -func foo110(x *int) *int { // ERROR "leaking param: x" - m := map[*int]*int{nil: x} // ERROR "map.* literal does not escape" +func foo110(x *int) *int { // ERROR "leaking param: x$" + m := map[*int]*int{nil: x} // ERROR "foo110 map\[\*int\]\*int literal does not escape$" return m[nil] } -func foo111(x *int) *int { // ERROR "leaking param: x" - m := []*int{x} // ERROR "\[\]\*int literal does not escape" +func foo111(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0" + m := []*int{x} // ERROR "foo111 \[\]\*int literal does not escape$" return m[0] } -func foo112(x *int) *int { // ERROR "leaking param: x" +func foo112(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" m := [1]*int{x} return m[0] } -func foo113(x *int) *int { // ERROR "leaking param: x" +func foo113(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" m := Bar{ii: x} return m.ii } -func foo114(x *int) *int { // ERROR "leaking param: x" - m := &Bar{ii: x} // ERROR "&Bar literal does not escape" +func foo114(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" + m := &Bar{ii: x} // ERROR "foo114 &Bar literal does not escape$" return m.ii } -func foo115(x *int) *int { // ERROR "leaking param: x" +func foo115(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1)) } func foo116(b bool) *int { if b { - x := 1 // ERROR "moved to heap: x" - return &x // ERROR "&x escapes to heap" + x := 1 // ERROR "moved to heap: x$" + return &x // ERROR "&x escapes to heap$" } else { - y := 1 // ERROR "moved to heap: y" - return &y // ERROR "&y escapes to heap" + y := 1 // ERROR "moved to heap: y$" + return &y // ERROR "&y escapes to heap$" } return nil } -func foo117(unknown func(interface{})) { // ERROR "unknown does not escape" - x := 1 // ERROR "moved to heap: x" - unknown(&x) // ERROR "&x escapes to heap" +func foo117(unknown func(interface{})) { // ERROR "foo117 unknown does not escape$" + x := 1 // ERROR "moved to heap: x$" + unknown(&x) // ERROR "&x escapes to heap$" } -func foo118(unknown func(*int)) { // ERROR "unknown does not escape" - x := 1 // ERROR "moved to heap: x" - unknown(&x) // ERROR "&x escapes to heap" +func foo118(unknown func(*int)) { // ERROR "foo118 unknown does not escape$" + x := 1 // ERROR "moved to heap: x$" + unknown(&x) // ERROR "&x escapes to heap$" } func external(*int) -func foo119(x *int) { // ERROR "leaking param: x" +func foo119(x *int) { // ERROR "leaking param: x$" external(x) } @@ -1079,16 +1152,16 @@ L100: func foo121() { for i := 0; i < 10; i++ { - defer myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap" - go myprint(nil, i) // ERROR "[.][.][.] argument escapes to heap" + defer myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + go myprint(nil, i) // ERROR "... argument escapes to heap$" "i escapes to heap$" } } // same as foo121 but check across import func foo121b() { for i := 0; i < 10; i++ { - defer fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap" - go fmt.Printf("%d", i) // ERROR "[.][.][.] argument escapes to heap" + defer fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" + go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" } } @@ -1098,7 +1171,7 @@ func foo122() { goto L1 L1: - i = new(int) // ERROR "new.int. does not escape" + i = new(int) // ERROR "foo122 new\(int\) does not escape$" _ = i } @@ -1107,25 +1180,25 @@ func foo123() { var i *int L1: - i = new(int) // ERROR "new.int. escapes to heap" + i = new(int) // ERROR "new\(int\) escapes to heap$" goto L1 _ = i } -func foo124(x **int) { // ERROR "x does not escape" - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes" - func() { // ERROR "func literal does not escape" - *x = p // ERROR "leaking closure reference p" +func foo124(x **int) { // ERROR "foo124 x does not escape$" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + func() { // ERROR "foo124 func literal does not escape$" + *x = p // ERROR "leaking closure reference p$" }() } -func foo125(ch chan *int) { // ERROR "does not escape" - var i int // ERROR "moved to heap" - p := &i // ERROR "&i escapes to heap" - func() { // ERROR "func literal does not escape" - ch <- p // ERROR "leaking closure reference p" +func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + func() { // ERROR "foo125 func literal does not escape$" + ch <- p // ERROR "leaking closure reference p$" }() } @@ -1133,9 +1206,9 @@ func foo126() { var px *int // loopdepth 0 for { // loopdepth 1 - var i int // ERROR "moved to heap" - func() { // ERROR "func literal does not escape" - px = &i // ERROR "&i escapes" + var i int // ERROR "moved to heap: i$" + func() { // ERROR "foo126 func literal does not escape$" + px = &i // ERROR "&i escapes to heap$" }() } _ = px @@ -1144,26 +1217,26 @@ func foo126() { var px *int func foo127() { - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes to heap" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" q := p px = q } func foo128() { var i int - p := &i // ERROR "&i does not escape" + p := &i // ERROR "foo128 &i does not escape$" q := p _ = q } func foo129() { - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes to heap" - func() { // ERROR "func literal does not escape" - q := p // ERROR "leaking closure reference p" - func() { // ERROR "func literal does not escape" - r := q // ERROR "leaking closure reference q" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + func() { // ERROR "foo129 func literal does not escape$" + q := p // ERROR "leaking closure reference p$" + func() { // ERROR "foo129.func1 func literal does not escape$" + r := q // ERROR "leaking closure reference q$" px = r }() }() @@ -1171,40 +1244,40 @@ func foo129() { func foo130() { for { - var i int // ERROR "moved to heap" - func() { // ERROR "func literal does not escape" - px = &i // ERROR "&i escapes" "leaking closure reference i" + var i int // ERROR "moved to heap: i$" + func() { // ERROR "foo130 func literal does not escape$" + px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$" }() } } func foo131() { - var i int // ERROR "moved to heap" - func() { // ERROR "func literal does not escape" - px = &i // ERROR "&i escapes" "leaking closure reference i" + var i int // ERROR "moved to heap: i$" + func() { // ERROR "foo131 func literal does not escape$" + px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$" }() } func foo132() { - var i int // ERROR "moved to heap" - go func() { // ERROR "func literal escapes to heap" - px = &i // ERROR "&i escapes" "leaking closure reference i" + var i int // ERROR "moved to heap: i$" + go func() { // ERROR "func literal escapes to heap$" + px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$" }() } func foo133() { - var i int // ERROR "moved to heap" - defer func() { // ERROR "func literal does not escape" - px = &i // ERROR "&i escapes" "leaking closure reference i" + var i int // ERROR "moved to heap: i$" + defer func() { // ERROR "foo133 func literal does not escape$" + px = &i // ERROR "&i escapes to heap$" "leaking closure reference i$" }() } func foo134() { var i int - p := &i // ERROR "&i does not escape" - func() { // ERROR "func literal does not escape" + p := &i // ERROR "foo134 &i does not escape$" + func() { // ERROR "foo134 func literal does not escape$" q := p - func() { // ERROR "func literal does not escape" + func() { // ERROR "foo134.func1 func literal does not escape$" r := q _ = r }() @@ -1212,11 +1285,11 @@ func foo134() { } func foo135() { - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes to heap" "moved to heap: p" - go func() { // ERROR "func literal escapes to heap" - q := p // ERROR "&p escapes to heap" - func() { // ERROR "func literal does not escape" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + go func() { // ERROR "func literal escapes to heap$" + q := p + func() { // ERROR "foo135.func1 func literal does not escape$" r := q _ = r }() @@ -1224,24 +1297,24 @@ func foo135() { } func foo136() { - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes to heap" "moved to heap: p" - go func() { // ERROR "func literal escapes to heap" - q := p // ERROR "&p escapes to heap" "leaking closure reference p" - func() { // ERROR "func literal does not escape" - r := q // ERROR "leaking closure reference q" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + go func() { // ERROR "func literal escapes to heap$" + q := p // ERROR "leaking closure reference p$" + func() { // ERROR "foo136.func1 func literal does not escape$" + r := q // ERROR "leaking closure reference q$" px = r }() }() } func foo137() { - var i int // ERROR "moved to heap: i" - p := &i // ERROR "&i escapes to heap" - func() { // ERROR "func literal does not escape" - q := p // ERROR "leaking closure reference p" "moved to heap: q" - go func() { // ERROR "func literal escapes to heap" - r := q // ERROR "&q escapes to heap" + var i int // ERROR "moved to heap: i$" + p := &i // ERROR "&i escapes to heap$" + func() { // ERROR "foo137 func literal does not escape$" + q := p // ERROR "leaking closure reference p$" + go func() { // ERROR "func literal escapes to heap$" + r := q _ = r }() }() @@ -1251,8 +1324,8 @@ func foo138() *byte { type T struct { x [1]byte } - t := new(T) // ERROR "new.T. escapes to heap" - return &t.x[0] // ERROR "&t.x.0. escapes to heap" + t := new(T) // ERROR "new\(T\) escapes to heap$" + return &t.x[0] // ERROR "&t.x\[0\] escapes to heap$" } func foo139() *byte { @@ -1261,8 +1334,8 @@ func foo139() *byte { y byte } } - t := new(T) // ERROR "new.T. escapes to heap" - return &t.x.y // ERROR "&t.x.y escapes to heap" + t := new(T) // ERROR "new\(T\) escapes to heap$" + return &t.x.y // ERROR "&t.x.y escapes to heap$" } // issue 4751 @@ -1274,8 +1347,8 @@ func foo140() interface{} { X string T *T } - t := &T{} // ERROR "&T literal escapes to heap" - return U{ + t := &T{} // ERROR "&T literal escapes to heap$" + return U{ // ERROR "U literal escapes to heap$" X: t.X, T: t, } @@ -1289,53 +1362,53 @@ func F2([]byte) //go:noescape -func F3(x []byte) // ERROR "F3 x does not escape" +func F3(x []byte) // ERROR "F3 x does not escape$" func F4(x []byte) func G() { var buf1 [10]byte - F1(buf1[:]) // ERROR "buf1 does not escape" + F1(buf1[:]) // ERROR "G buf1 does not escape$" - var buf2 [10]byte // ERROR "moved to heap: buf2" - F2(buf2[:]) // ERROR "buf2 escapes to heap" + var buf2 [10]byte // ERROR "moved to heap: buf2$" + F2(buf2[:]) // ERROR "buf2 escapes to heap$" var buf3 [10]byte - F3(buf3[:]) // ERROR "buf3 does not escape" + F3(buf3[:]) // ERROR "G buf3 does not escape$" - var buf4 [10]byte // ERROR "moved to heap: buf4" - F4(buf4[:]) // ERROR "buf4 escapes to heap" + var buf4 [10]byte // ERROR "moved to heap: buf4$" + F4(buf4[:]) // ERROR "buf4 escapes to heap$" } type Tm struct { x int } -func (t *Tm) M() { // ERROR "t does not escape" +func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$" } func foo141() { var f func() - t := new(Tm) // ERROR "escapes to heap" - f = t.M // ERROR "t.M does not escape" + t := new(Tm) // ERROR "new\(Tm\) escapes to heap$" + f = t.M // ERROR "foo141 t.M does not escape$" _ = f } var gf func() func foo142() { - t := new(Tm) // ERROR "escapes to heap" - gf = t.M // ERROR "t.M escapes to heap" + t := new(Tm) // ERROR "new\(Tm\) escapes to heap$" + gf = t.M // ERROR "t.M escapes to heap$" } // issue 3888. func foo143() { for i := 0; i < 1000; i++ { - func() { // ERROR "func literal does not escape" + func() { // ERROR "foo143 func literal does not escape$" for i := 0; i < 1; i++ { var t Tm - t.M() // ERROR "t does not escape" + t.M() // ERROR "foo143.func1 t does not escape$" } }() } @@ -1351,9 +1424,9 @@ func foo144a(*int) func foo144() { var x int - foo144a(&x) // ERROR "&x does not escape" + foo144a(&x) // ERROR "foo144 &x does not escape$" var y int - foo144b(&y) // ERROR "&y does not escape" + foo144b(&y) // ERROR "foo144 &y does not escape$" } //go:noescape @@ -1366,38 +1439,38 @@ type List struct { Next *List } -func foo145(l List) { // ERROR "l does not escape" +func foo145(l List) { // ERROR "foo145 l does not escape$" var p *List - for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + for p = &l; p.Next != nil; p = p.Next { // ERROR "foo145 &l does not escape$" } } -func foo146(l List) { // ERROR "l does not escape" +func foo146(l List) { // ERROR "foo146 l does not escape$" var p *List - p = &l // ERROR "&l does not escape" + p = &l // ERROR "foo146 &l does not escape$" for ; p.Next != nil; p = p.Next { } } -func foo147(l List) { // ERROR "l does not escape" +func foo147(l List) { // ERROR "foo147 l does not escape$" var p *List - p = &l // ERROR "&l does not escape" + p = &l // ERROR "foo147 &l does not escape$" for p.Next != nil { p = p.Next } } -func foo148(l List) { // ERROR " l does not escape" - for p := &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" +func foo148(l List) { // ERROR "foo148 l does not escape$" + for p := &l; p.Next != nil; p = p.Next { // ERROR "foo148 &l does not escape$" } } // related: address of variable should have depth of variable, not of loop -func foo149(l List) { // ERROR " l does not escape" +func foo149(l List) { // ERROR "foo149 l does not escape$" var p *List for { - for p = &l; p.Next != nil; p = p.Next { // ERROR "&l does not escape" + for p = &l; p.Next != nil; p = p.Next { // ERROR "foo149 &l does not escape$" } } } @@ -1406,44 +1479,44 @@ func foo149(l List) { // ERROR " l does not escape" var save150 []byte -func foo150(x ...byte) { // ERROR "leaking param: x" +func foo150(x ...byte) { // ERROR "leaking param: x$" save150 = x } func bar150() { - foo150(1, 2, 3) // ERROR "[.][.][.] argument escapes to heap" + foo150(1, 2, 3) // ERROR "... argument escapes to heap$" } // issue 7931: bad handling of slice of array var save151 *int -func foo151(x *int) { // ERROR "leaking param: x" +func foo151(x *int) { // ERROR "leaking param: x$" save151 = x } func bar151() { - var a [64]int // ERROR "moved to heap: a" + var a [64]int // ERROR "moved to heap: a$" a[4] = 101 - foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap" "&a escapes to heap" + foo151(&(&a)[4:8][0]) // ERROR "&\(&a\)\[4:8\]\[0\] escapes to heap$" "&a escapes to heap$" } func bar151b() { - var a [10]int // ERROR "moved to heap: a" - b := a[:] // ERROR "a escapes to heap" - foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap" + var a [10]int // ERROR "moved to heap: a$" + b := a[:] // ERROR "a escapes to heap$" + foo151(&b[4:8][0]) // ERROR "&b\[4:8\]\[0\] escapes to heap$" } func bar151c() { - var a [64]int // ERROR "moved to heap: a" + var a [64]int // ERROR "moved to heap: a$" a[4] = 101 - foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap" "&a escapes to heap" + foo151(&(&a)[4:8:8][0]) // ERROR "&\(&a\)\[4:8:8\]\[0\] escapes to heap$" "&a escapes to heap$" } func bar151d() { - var a [10]int // ERROR "moved to heap: a" - b := a[:] // ERROR "a escapes to heap" - foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap" + var a [10]int // ERROR "moved to heap: a$" + b := a[:] // ERROR "a escapes to heap$" + foo151(&b[4:8:8][0]) // ERROR "&b\[4:8:8\]\[0\] escapes to heap$" } // issue 8120 @@ -1452,7 +1525,7 @@ type U struct { s *string } -func (u *U) String() *string { // ERROR "leaking param u content to result ~r0" +func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$" return u.s } @@ -1460,35 +1533,298 @@ type V struct { s *string } -func NewV(u U) *V { // ERROR "leaking param: u" - return &V{u.String()} // ERROR "&V literal escapes to heap" "u does not escape" +// BAD -- level of leak ought to be 0 +func NewV(u U) *V { // ERROR "leaking param: u to result ~r1 level=-1" + return &V{u.String()} // ERROR "&V literal escapes to heap$" "NewV u does not escape" } func foo152() { - a := "a" // ERROR "moved to heap: a" - u := U{&a} // ERROR "&a escapes to heap" + a := "a" // ERROR "moved to heap: a$" + u := U{&a} // ERROR "&a escapes to heap$" v := NewV(u) println(v) } // issue 8176 - &x in type switch body not marked as escaping -func foo153(v interface{}) *int { // ERROR "leaking param: v" +func foo153(v interface{}) *int { // ERROR "leaking param: v to result ~r1 level=-1$" switch x := v.(type) { - case int: // ERROR "moved to heap: x" - return &x // ERROR "&x escapes to heap" + case int: // ERROR "moved to heap: x$" + return &x // ERROR "&x escapes to heap$" } panic(0) } // issue 8185 - &result escaping into result -func f() (x int, y *int) { // ERROR "moved to heap: x" - y = &x // ERROR "&x escapes to heap" +func f() (x int, y *int) { // ERROR "moved to heap: x$" + y = &x // ERROR "&x escapes to heap$" return } -func g() (x interface{}) { // ERROR "moved to heap: x" - x = &x // ERROR "&x escapes to heap" +func g() (x interface{}) { // ERROR "moved to heap: x$" + x = &x // ERROR "&x escapes to heap$" return } + +var sink interface{} + +type Lit struct { + p *int +} + +func ptrlitNoescape() { + // Both literal and element do not escape. + i := 0 + x := &Lit{&i} // ERROR "ptrlitNoescape &Lit literal does not escape$" "ptrlitNoescape &i does not escape$" + _ = x +} + +func ptrlitNoEscape2() { + // Literal does not escape, but element does. + i := 0 // ERROR "moved to heap: i$" + x := &Lit{&i} // ERROR "&i escapes to heap$" "ptrlitNoEscape2 &Lit literal does not escape$" + sink = *x // ERROR "\*x escapes to heap$" +} + +func ptrlitEscape() { + // Both literal and element escape. + i := 0 // ERROR "moved to heap: i$" + x := &Lit{&i} // ERROR "&Lit literal escapes to heap$" "&i escapes to heap$" + sink = x // ERROR "x escapes to heap$" +} + +// self-assignments + +type Buffer struct { + arr [64]byte + buf1 []byte + buf2 []byte + str1 string + str2 string +} + +func (b *Buffer) foo() { // ERROR "\(\*Buffer\).foo b does not escape$" + b.buf1 = b.buf1[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment to b.buf1$" + b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment to b.buf1$" + b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment to b.buf1$" + b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment to b.buf1$" +} + +func (b *Buffer) bar() { // ERROR "leaking param: b$" + b.buf1 = b.arr[1:2] // ERROR "b.arr escapes to heap$" +} + +func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$" + b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment to b.str1$" + b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment to b.str1$" +} + +func (b *Buffer) bat() { // ERROR "leaking param content: b$" + o := new(Buffer) // ERROR "new\(Buffer\) escapes to heap$" + o.buf1 = b.buf1[1:2] + sink = o // ERROR "o escapes to heap$" +} + +func quux(sp *string, bp *[]byte) { // ERROR "quux bp does not escape$" "quux sp does not escape$" + *sp = (*sp)[1:2] // ERROR "quux ignoring self-assignment to \*sp$" + *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment to \*bp$" +} + +type StructWithString struct { + p *int + s string +} + +// This is escape analysis false negative. +// We assign the pointer to x.p but leak x.s. Escape analysis coarsens flows +// to just x, and thus &i looks escaping. +func fieldFlowTracking() { + var x StructWithString + i := 0 // ERROR "moved to heap: i$" + x.p = &i // ERROR "&i escapes to heap$" + sink = x.s // ERROR "x.s escapes to heap$" +} + +// String operations. + +func slicebytetostring0() { + b := make([]byte, 20) // ERROR "slicebytetostring0 make\(\[\]byte, 20\) does not escape$" + s := string(b) // ERROR "slicebytetostring0 string\(b\) does not escape$" + _ = s +} + +func slicebytetostring1() { + b := make([]byte, 20) // ERROR "slicebytetostring1 make\(\[\]byte, 20\) does not escape$" + s := string(b) // ERROR "slicebytetostring1 string\(b\) does not escape$" + s1 := s[0:1] + _ = s1 +} + +func slicebytetostring2() { + b := make([]byte, 20) // ERROR "slicebytetostring2 make\(\[\]byte, 20\) does not escape$" + s := string(b) // ERROR "string\(b\) escapes to heap$" + s1 := s[0:1] // ERROR "moved to heap: s1$" + sink = &s1 // ERROR "&s1 escapes to heap$" +} + +func slicebytetostring3() { + b := make([]byte, 20) // ERROR "slicebytetostring3 make\(\[\]byte, 20\) does not escape$" + s := string(b) // ERROR "string\(b\) escapes to heap$" + s1 := s[0:1] + sink = s1 // ERROR "s1 escapes to heap$" +} + +func addstr0() { + s0 := "a" + s1 := "b" + s := s0 + s1 // ERROR "addstr0 s0 \+ s1 does not escape$" + _ = s +} + +func addstr1() { + s0 := "a" + s1 := "b" + s := "c" + s += s0 + s1 // ERROR "addstr1 s0 \+ s1 does not escape$" + _ = s +} + +func addstr2() { + b := make([]byte, 20) // ERROR "addstr2 make\(\[\]byte, 20\) does not escape$" + s0 := "a" + s := string(b) + s0 // ERROR "addstr2 string\(b\) \+ s0 does not escape$" "addstr2 string\(b\) does not escape$" + _ = s +} + +func addstr3() { + s0 := "a" + s1 := "b" + s := s0 + s1 // ERROR "s0 \+ s1 escapes to heap$" + s2 := s[0:1] + sink = s2 // ERROR "s2 escapes to heap$" +} + +func intstring0() bool { + // string does not escape + x := '0' + s := string(x) // ERROR "intstring0 string\(x\) does not escape$" + return s == "0" +} + +func intstring1() string { + // string does not escape, but the buffer does + x := '0' + s := string(x) // ERROR "string\(x\) escapes to heap$" + return s +} + +func intstring2() { + // string escapes to heap + x := '0' + s := string(x) // ERROR "moved to heap: s$" "string\(x\) escapes to heap$" + sink = &s // ERROR "&s escapes to heap$" +} + +func stringtoslicebyte0() { + s := "foo" + x := []byte(s) // ERROR "stringtoslicebyte0 \(\[\]byte\)\(s\) does not escape$" + _ = x +} + +func stringtoslicebyte1() []byte { + s := "foo" + return []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$" +} + +func stringtoslicebyte2() { + s := "foo" + sink = []byte(s) // ERROR "\(\[\]byte\)\(s\) escapes to heap$" +} + +func stringtoslicerune0() { + s := "foo" + x := []rune(s) // ERROR "stringtoslicerune0 \(\[\]rune\)\(s\) does not escape$" + _ = x +} + +func stringtoslicerune1() []rune { + s := "foo" + return []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$" +} + +func stringtoslicerune2() { + s := "foo" + sink = []rune(s) // ERROR "\(\[\]rune\)\(s\) escapes to heap$" +} + +func slicerunetostring0() { + r := []rune{1, 2, 3} // ERROR "slicerunetostring0 \[\]rune literal does not escape$" + s := string(r) // ERROR "slicerunetostring0 string\(r\) does not escape$" + _ = s +} + +func slicerunetostring1() string { + r := []rune{1, 2, 3} // ERROR "slicerunetostring1 \[\]rune literal does not escape$" + return string(r) // ERROR "string\(r\) escapes to heap$" +} + +func slicerunetostring2() { + r := []rune{1, 2, 3} // ERROR "slicerunetostring2 \[\]rune literal does not escape$" + sink = string(r) // ERROR "string\(r\) escapes to heap$" +} + +func makemap0() { + m := make(map[int]int) // ERROR "makemap0 make\(map\[int\]int\) does not escape$" + m[0] = 0 + m[1]++ + delete(m, 1) + sink = m[0] // ERROR "m\[0\] escapes to heap$" +} + +func makemap1() map[int]int { + return make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$" +} + +func makemap2() { + m := make(map[int]int) // ERROR "make\(map\[int\]int\) escapes to heap$" + sink = m // ERROR "m escapes to heap$" +} + +func nonescapingEface(m map[interface{}]bool) bool { // ERROR "nonescapingEface m does not escape$" + return m["foo"] // ERROR "nonescapingEface .foo. does not escape$" +} + +func nonescapingIface(m map[M]bool) bool { // ERROR "nonescapingIface m does not escape$" + return m[MV(0)] // ERROR "nonescapingIface MV\(0\) does not escape$" +} + +func issue10353() { + x := new(int) // ERROR "new\(int\) escapes to heap$" + issue10353a(x)() +} + +func issue10353a(x *int) func() { // ERROR "leaking param: x to result ~r1 level=-1$" + return func() { // ERROR "func literal escapes to heap$" + println(*x) + } +} + +func issue10353b() { + var f func() + for { + x := new(int) // ERROR "new\(int\) escapes to heap$" + f = func() { // ERROR "func literal escapes to heap$" + println(*x) + } + } + _ = f +} + +func issue11387(x int) func() int { + f := func() int { return x } // ERROR "func literal escapes to heap" + slice1 := []func() int{f} // ERROR "\[\].* does not escape" + slice2 := make([]func() int, 1) // ERROR "make\(.*\) does not escape" + copy(slice2, slice1) + return slice2[0] +} |