1
0
mirror of https://github.com/golang/go synced 2024-11-25 08:57:58 -07:00
go/test/escape2.go
Russ Cox 77f0bdce07 gc: fix arm build
Escape analysis was incorrectly assuming that
functions without bodies don't leak their
parameters.  This meant that sync/atomic's
TestAddInt64 was allocating x on its stack,
and then x was not properly aligned for use
with the atomic 64-bit instructions.  Obviously
we should figure out the alignment story on 5g
too, but this fix is correct and should restore the
build to 'ok'.

TBR=lvd
CC=golang-dev
https://golang.org/cl/4964047
2011-08-28 23:29:34 -04:00

783 lines
16 KiB
Go

// errchk -0 $G -m $D/$F.go
// Copyright 2010 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.
package foo
import "unsafe"
var gxx *int
func foo1(x int) { // ERROR "moved to heap: NAME-x"
gxx = &x // ERROR "&x escapes to heap"
}
func foo2(yy *int) { // ERROR "leaking param: NAME-yy"
gxx = yy
}
func foo3(x int) *int { // ERROR "moved to heap: NAME-x"
return &x // ERROR "&x escapes to heap"
}
type T *T
func foo3b(t T) { // ERROR "leaking param: NAME-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"
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 foo6(xx **int, yy *int) { // ERROR "xx does not escape" "leaking param: NAME-yy"
*xx = yy
}
func foo7(xx **int, yy *int) { // ERROR "xx does not escape" "yy does not escape"
**xx = *yy
}
func foo8(xx, yy *int) int { // ERROR "xx does not escape" "yy does not escape"
xx = yy
return *xx
}
func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param: NAME-yy"
xx = yy
return xx
}
func foo10(xx, yy *int) { // ERROR "xx does not escape" "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 = *yy
return x
}
var xxx **int
func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy"
xxx = yyy
}
func foo13(yyy **int) { // ERROR "yyy does not escape"
*xxx = *yyy
}
func foo14(yyy **int) { // ERROR "yyy does not escape"
**xxx = **yyy
}
func foo15(yy *int) { // ERROR "moved to heap: NAME-yy"
xxx = &yy // ERROR "&yy escapes to heap"
}
func foo16(yy *int) { // ERROR "leaking param: NAME-yy"
*xxx = yy
}
func foo17(yy *int) { // ERROR "yy does not escape"
**xxx = *yy
}
func foo18(y int) { // ERROR "moved to heap: "NAME-y"
*xxx = &y // ERROR "&y escapes to heap"
}
func foo19(y int) {
**xxx = y
}
type Bar struct {
i int
ii *int
}
func NewBar() *Bar {
return &Bar{42, nil} // ERROR "&struct literal escapes to heap"
}
func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x"
return &Bar{42, x} // ERROR "&struct literal escapes to heap"
}
func NewBarp2(x *int) *Bar { // ERROR "x does not escape"
return &Bar{*x, nil} // ERROR "&struct literal escapes to heap"
}
func (b *Bar) NoLeak() int { // ERROR "b does not escape"
return *(b.ii)
}
func (b *Bar) AlsoNoLeak() *int { // ERROR "b does not escape"
return b.ii
}
type Bar2 struct {
i [12]int
ii []int
}
func NewBar2() *Bar2 {
return &Bar2{[12]int{42}, nil} // ERROR "&struct literal escapes to heap"
}
func (b *Bar2) NoLeak() int { // ERROR "b does not escape"
return b.i[0]
}
func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b"
return b.i[:] // ERROR "&b.i escapes to heap"
}
func (b *Bar2) AlsoNoLeak() []int { // ERROR "b does not escape"
return b.ii[0:1]
}
func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b"
b.ii = b.i[0:4] // ERROR "&b.i escapes to heap"
}
func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b"
var buf []int
buf = b.i[0:] // ERROR "&b.i escapes to heap"
b.ii = buf
}
func foo21() func() int {
x := 42 // ERROR "moved to heap: NAME-x"
return func() int { // ERROR "func literal escapes to heap"
return x // ERROR "&x escapes to heap"
}
}
func foo22() int {
x := 42
return func() int { // ERROR "func literal does not escape"
return x
}()
}
func foo23(x int) func() int { // ERROR "moved to heap: NAME-x"
return func() int { // ERROR "func literal escapes to heap"
return x // ERROR "&x escapes to heap"
}
}
func foo23a(x int) func() int { // ERROR "moved to heap: NAME-x"
f := func() int { // ERROR "func literal escapes to heap"
return x // ERROR "&x escapes to heap"
}
return f
}
func foo23b(x int) *(func() int) { // ERROR "moved to heap: NAME-x"
f := func() int { return x } // ERROR "moved to heap: NAME-f" "func literal escapes to heap" "&x escapes to heap"
return &f // ERROR "&f escapes to heap"
}
func foo24(x int) int {
return func() int { // ERROR "func literal does not escape"
return x
}()
}
var x *int
func fooleak(xx *int) int { // ERROR "leaking param: NAME-xx"
x = xx
return *x
}
func foonoleak(xx *int) int { // ERROR "xx does not escape"
return *x + *xx
}
func foo31(x int) int { // ERROR "moved to heap: NAME-x"
return fooleak(&x) // ERROR "&x escapes to heap"
}
func foo32(x int) int {
return foonoleak(&x) // ERROR "&x does not escape"
}
type Foo struct {
xx *int
x int
}
var F Foo
var pf *Foo
func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f"
pf = f
}
func (f *Foo) foonoleak() { // ERROR "f does not escape"
F.x = f.x
}
func (f *Foo) Leak() { // ERROR "leaking param: NAME-f"
f.fooleak()
}
func (f *Foo) NoLeak() { // ERROR "f does not escape"
f.foonoleak()
}
func foo41(x int) { // ERROR "moved to heap: NAME-x"
F.xx = &x // ERROR "&x escapes to heap"
}
func (f *Foo) foo42(x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
f.xx = &x // ERROR "&x escapes to heap"
}
func foo43(f *Foo, x int) { // ERROR "f does not escape" "moved to heap: NAME-x"
f.xx = &x // ERROR "&x escapes to heap"
}
func foo44(yy *int) { // ERROR "leaking param: NAME-yy"
F.xx = yy
}
func (f *Foo) foo45() { // ERROR "f does not escape"
F.x = f.x
}
func (f *Foo) foo46() { // ERROR "f does not escape"
F.xx = f.xx
}
func (f *Foo) foo47() { // ERROR "leaking param: NAME-f"
f.xx = &f.x // ERROR "&f.x escapes to heap"
}
var ptrSlice []*int
func foo50(i *int) { // ERROR "leaking param: NAME-i"
ptrSlice[0] = i
}
var ptrMap map[*int]*int
func foo51(i *int) { // ERROR "leaking param: NAME-i"
ptrMap[i] = i
}
func indaddr1(x int) *int { // ERROR "moved to heap: NAME-x"
return &x // ERROR "&x escapes to heap"
}
func indaddr2(x *int) *int { // ERROR "leaking param: NAME-x"
return *&x // ERROR "&x does not escape"
}
func indaddr3(x *int32) *int { // ERROR "leaking param: NAME-x"
return *(**int)(unsafe.Pointer(&x)) // ERROR "&x does not escape"
}
// From package math:
func Float32bits(f float32) uint32 {
return *(*uint32)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
}
func Float32frombits(b uint32) float32 {
return *(*float32)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
}
func Float64bits(f float64) uint64 {
return *(*uint64)(unsafe.Pointer(&f)) // ERROR "&f does not escape"
}
func Float64frombits(b uint64) float64 {
return *(*float64)(unsafe.Pointer(&b)) // ERROR "&b does not escape"
}
// contrast with
func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: NAME-f"
return (*uint64)(unsafe.Pointer(&f)) // ERROR "&f escapes to heap"
}
func float64ptrbitsptr(f *float64) *uint64 { // ERROR "leaking param: NAME-f"
return (*uint64)(unsafe.Pointer(f))
}
func typesw(i interface{}) *int { // ERROR "leaking param: NAME-i"
switch val := i.(type) {
case *int:
return val
case *int8:
v := int(*val) // ERROR "moved to heap: NAME-v"
return &v // ERROR "&v escapes to heap"
}
return nil
}
func exprsw(i *int) *int { // ERROR "leaking param: NAME-i"
switch j := i; *j + 110 {
case 12:
return j
case 42:
return nil
}
return nil
}
// assigning to an array element is like assigning to the array
func foo60(i *int) *int { // ERROR "leaking param: NAME-i"
var a [12]*int
a[0] = i
return a[1]
}
func foo60a(i *int) *int { // ERROR "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: NAME-i"
type S struct {
a, b *int
}
var s S
s.a = i
return s.b
}
func foo61a(i *int) *int { // ERROR "i does not escape"
type S struct {
a, b *int
}
var s S
s.a = i
return nil
}
// 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: NAME-i"
type S struct {
a, b *int
}
s := new(S) // ERROR "new[(]S[)] does not escape"
s.a = i
return nil // s.b
}
type M interface {
M()
}
func foo63(m M) { // ERROR "m does not escape"
}
func foo64(m M) { // ERROR "leaking param: NAME-m"
m.M()
}
type MV int
func (MV) M() {}
func foo65() {
var mv MV
foo63(&mv) // ERROR "&mv does not escape"
}
func foo66() {
var mv MV // ERROR "moved to heap: NAME-mv"
foo64(&mv) // ERROR "&mv escapes to heap"
}
func foo67() {
var mv MV
foo63(mv)
}
func foo68() {
var mv MV
foo64(mv) // escapes but it's an int so irrelevant
}
func foo69(m M) { // ERROR "leaking param: NAME-m"
foo64(m)
}
func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: NAME-m"
m = mv1
foo64(m)
}
func foo71(x *int) []*int { // ERROR "leaking param: NAME-x"
var y []*int
y = append(y, x)
return y
}
func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x"
var y []*int
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"
}
func foo72aa() [10]*int {
var x int // ERROR "moved to heap: NAME-x"
var y [10]*int
y[0] = &x // ERROR "&x escapes to heap"
return y
}
func foo72a() {
var y [10]*int
for i := 0; i < 10; i++ {
// escapes its scope
x := i // ERROR "moved to heap: NAME-x"
y[i] = &x // ERROR "&x escapes to heap"
}
return
}
func foo72b() [10]*int {
var y [10]*int
for i := 0; i < 10; i++ {
x := i // ERROR "moved to heap: NAME-x"
y[i] = &x // ERROR "&x escapes to heap"
}
return y
}
// issue 2145
func foo73() {
s := []int{3, 2, 1} // ERROR "slice literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: NAME-vv"
// actually just escapes its scope
defer func() { // ERROR "func literal escapes to heap"
println(vv) // ERROR "&vv escapes to heap"
}()
}
}
func foo74() {
s := []int{3, 2, 1} // ERROR "slice literal does not escape"
for _, v := range s {
vv := v // ERROR "moved to heap: NAME-vv"
// actually just escapes its scope
fn := func() { // ERROR "func literal escapes to heap"
println(vv) // ERROR "&vv escapes to heap"
}
defer fn()
}
}
func myprint(y *int, x ...interface{}) *int { // ERROR "x does not escape" "leaking param: NAME-y"
return y
}
func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "y does not escape" "leaking param: NAME-x"
return &x[0] // ERROR "&x.0. escapes to heap"
}
func foo75(z *int) { // ERROR "leaking param: NAME-z"
myprint(z, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo75a(z *int) { // ERROR "z does not escape"
myprint1(z, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
}
func foo76(z *int) { // ERROR "leaking param: NAME-z"
myprint(nil, z) // ERROR "[.][.][.] argument does not escape"
}
func foo76a(z *int) { // ERROR "leaking param: NAME-z"
myprint1(nil, z) // ERROR "[.][.][.] argument escapes to heap"
}
func foo76b() {
myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo76c() {
myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
}
func foo76d() {
defer myprint(nil, 1, 2, 3) // ERROR "[.][.][.] argument does not escape"
}
func foo76e() {
defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
}
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"
}
}
func foo76g() {
for {
defer myprint1(nil, 1, 2, 3) // ERROR "[.][.][.] argument escapes to heap"
}
}
func foo77(z []interface{}) { // ERROR "z does not escape"
myprint(nil, z...) // z does not escape
}
func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z"
myprint1(nil, z...)
}
func foo78(z int) *int { // ERROR "moved to heap: NAME-z"
return &z // ERROR "&z escapes to heap"
}
func foo78a(z int) *int { // ERROR "moved to heap: NAME-z"
y := &z // ERROR "&z escapes to heap"
x := &y // ERROR "&y does not escape"
return *x // really return y
}
func foo79() *int {
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
return nil
}
func foo81() *int {
for {
z := new(int) // ERROR "new[(]int[)] does not escape"
_ = z
}
return nil
}
type Fooer interface {
Foo()
}
type LimitedFooer struct {
Fooer
N int64
}
func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r"
return &LimitedFooer{r, n} // ERROR "&struct literal escapes to heap"
}
func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
}
func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
}
func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x"
return [2]*int{x, nil}
}
// does not leak c
func foo93(c chan *int) *int { // ERROR "c does not escape"
for v := range c {
return v
}
return nil
}
// does not leak m
func foo94(m map[*int]*int, b bool) *int { // ERROR "m does not escape"
for k, v := range m {
if b {
return k
}
return v
}
return nil
}
// does leak x
func foo95(m map[*int]*int, x *int) { // ERROR "m does not escape" "leaking param: NAME-x"
m[x] = x
}
// does not leak m
func foo96(m []*int) *int { // ERROR "m does not escape"
return m[0]
}
// does leak m
func foo97(m [1]*int) *int { // ERROR "leaking param: NAME-m"
return m[0]
}
// does not leak m
func foo98(m map[int]*int) *int { // ERROR "m does not escape"
return m[0]
}
// does leak m
func foo99(m *[1]*int) []*int { // ERROR "leaking param: NAME-m"
return m[:]
}
// does not leak m
func foo100(m []*int) *int { // ERROR "m does not escape"
for _, v := range m {
return v
}
return nil
}
// does leak m
func foo101(m [1]*int) *int { // ERROR "leaking param: NAME-m"
for _, v := range m {
return v
}
return nil
}
// does not leak m
func foo101a(m [1]*int) *int { // ERROR "m does not escape"
for i := range m { // ERROR "moved to heap: NAME-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: NAME-x"
m[0] = x
}
// does not leak x
func foo103(m [1]*int, x *int) { // ERROR "m does not escape" "x does not escape"
m[0] = x
}
var y []*int
// does not leak x
func foo104(x []*int) { // ERROR "x does not escape"
copy(y, x)
}
// does not leak x
func foo105(x []*int) { // ERROR "x does not escape"
_ = append(y, x...)
}
// does leak x
func foo106(x *int) { // ERROR "leaking param: NAME-x"
_ = append(y, x)
}
func foo107(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
return map[*int]*int{x: nil} // ERROR "map literal escapes to heap"
}
func foo108(x *int) map[*int]*int { // ERROR "leaking param: NAME-x"
return map[*int]*int{nil: x} // ERROR "map literal escapes to heap"
}
func foo109(x *int) *int { // ERROR "leaking param: NAME-x"
m := map[*int]*int{x: nil} // ERROR "map literal does not escape"
for k, _ := range m {
return k
}
return nil
}
func foo110(x *int) *int { // ERROR "leaking param: NAME-x"
m := map[*int]*int{nil: x} // ERROR "map literal does not escape"
return m[nil]
}
func foo111(x *int) *int { // ERROR "leaking param: NAME-x"
m := []*int{x} // ERROR "slice literal does not escape"
return m[0]
}
func foo112(x *int) *int { // ERROR "leaking param: NAME-x"
m := [1]*int{x}
return m[0]
}
func foo113(x *int) *int { // ERROR "leaking param: NAME-x"
m := Bar{ii: x}
return m.ii
}
func foo114(x *int) *int { // ERROR "leaking param: NAME-x"
m := &Bar{ii: x} // ERROR "&struct literal does not escape"
return m.ii
}
func foo115(x *int) *int { // ERROR "leaking param: NAME-x"
return (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(x)) + 1))
}
func foo116(b bool) *int {
if b {
x := 1 // ERROR "moved to heap: NAME-x"
return &x // ERROR "&x escapes to heap"
} else {
y := 1 // ERROR "moved to heap: NAME-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: NAME-x"
unknown(&x) // ERROR "&x escapes to heap"
}
func foo118(unknown func(*int)) { // ERROR "unknown does not escape"
x := 1 // ERROR "moved to heap: NAME-x"
unknown(&x) // ERROR "&x escapes to heap"
}
func external(*int)
func foo119(x *int) { // ERROR "leaking param: NAME-x"
external(x)
}