diff --git a/test/escape2.go b/test/escape2.go index f682621c25..f9b1e3f1cc 100644 --- a/test/escape2.go +++ b/test/escape2.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape2n.go b/test/escape2n.go index 2fd26f7c5c..390b27bd53 100644 --- a/test/escape2n.go +++ b/test/escape2n.go @@ -1,4 +1,4 @@ -// errorcheck -0 -N -m -l -newescape=true +// errorcheck -0 -N -m -l // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape5.go b/test/escape5.go index 11cab629a7..cbbccb4109 100644 --- a/test/escape5.go +++ b/test/escape5.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_because.go b/test/escape_because.go deleted file mode 100644 index e0a4214e7c..0000000000 --- a/test/escape_because.go +++ /dev/null @@ -1,209 +0,0 @@ -// errorcheck -0 -m -m -l -newescape=false - -// 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. - -// Note the doubled -m; this tests the "because" explanations for escapes, -// and is likely to be annoyingly fragile under compiler change. -// As long as the explanations look reasonably sane, meaning eyeball verify output of -// go build -gcflags '-l -m -m' escape_because.go -// and investigate changes, feel free to update with -// go run run.go -update_errors -- escape_because.go - -package main - -func main() { -} - -var sink interface{} - -type pair struct { - x, y *int -} - -type Pairy interface { - EqualParts() bool -} - -func (p *pair) EqualParts() bool { // ERROR "\(\*pair\).EqualParts p does not escape$" - return p != nil && (p.x == p.y || *p.x == *p.y) -} - -func f1(p *int) { // ERROR "from \[3\]\*int literal \(array literal element\) at escape_because.go:34$" "from a \(assigned\) at escape_because.go:34$" "from a \(interface-converted\) at escape_because.go:35$" "from sink \(assigned to top level variable\) at escape_because.go:35$" "leaking param: p$" - a := [3]*int{p, nil, nil} - sink = a // ERROR "a escapes to heap$" "from sink \(assigned to top level variable\) at escape_because.go:35$" - -} - -func f2(q *int) { // ERROR "from &u \(address-of\) at escape_because.go:43$" "from &u \(interface-converted\) at escape_because.go:43$" "from pair literal \(struct literal element\) at escape_because.go:41$" "from s \(assigned\) at escape_because.go:40$" "from sink \(assigned to top level variable\) at escape_because.go:43$" "from t \(assigned\) at escape_because.go:41$" "from u \(assigned\) at escape_because.go:42$" "leaking param: q$" - s := q - t := pair{s, nil} - u := t // ERROR "moved to heap: u$" - sink = &u // ERROR "&u escapes to heap$" "from sink \(assigned to top level variable\) at escape_because.go:43$" -} - -func f3(r *int) interface{} { // ERROR "from \[\]\*int literal \(slice-literal-element\) at escape_because.go:47$" "from c \(assigned\) at escape_because.go:47$" "from c \(interface-converted\) at escape_because.go:48$" "from ~r1 \(return\) at escape_because.go:48$" "leaking param: r" - c := []*int{r} // ERROR "\[\]\*int literal escapes to heap$" "from c \(assigned\) at escape_because.go:47$" "from c \(interface-converted\) at escape_because.go:48$" "from ~r1 \(return\) at escape_because.go:48$" - return c // "return" // ERROR "c escapes to heap$" "from ~r1 \(return\) at escape_because.go:48$" -} - -func f4(a *int, s []*int) int { // ERROR "from \*s \(indirection\) at escape_because.go:51$" "from append\(s, a\) \(appended to slice\) at escape_because.go:52$" "from append\(s, a\) \(appendee slice\) at escape_because.go:52$" "leaking param content: s$" "leaking param: a$" - s = append(s, a) - return *(s[0]) -} - -func f5(s1, s2 []*int) int { // ERROR "from \*s1 \(indirection\) at escape_because.go:56$" "from \*s2 \(indirection\) at escape_because.go:56$" "from append\(s1, s2...\) \(appended slice...\) at escape_because.go:57$" "from append\(s1, s2...\) \(appendee slice\) at escape_because.go:57$" "leaking param content: s1$" "leaking param content: s2$" - s1 = append(s1, s2...) - return *(s1[0]) -} - -func f6(x, y *int) bool { // ERROR "f6 x does not escape$" "f6 y does not escape$" - p := pair{x, y} - var P Pairy = &p // ERROR "f6 &p does not escape$" - pp := P.(*pair) - return pp.EqualParts() -} - -func f7(x map[int]*int, y int) *int { // ERROR "f7 x does not escape$" - z, ok := x[y] - if !ok { - return nil - } - return z -} - -func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go:78$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$" "leaking param: y$" "moved to heap: x$" - if x <= 0 { - return y - } - x-- - return f8(*y, &x) -} - -func f9(x int, y ...*int) *int { // ERROR "from y\[0\] \(dot of pointer\) at escape_because.go:86$" "from ~r2 \(return\) at escape_because.go:86$" "from ~r2 \(returned from recursive function\) at escape_because.go:84$" "leaking param content: y$" "leaking param: y to result ~r2 level=1$" "moved to heap: x$" - if x <= 0 { - return y[0] - } - x-- - return f9(*y[0], &x) // ERROR "f9 ... argument does not escape$" -} - -func f10(x map[*int]*int, y, z *int) *int { // ERROR "f10 x does not escape$" "from x\[y\] \(key of map put\) at escape_because.go:93$" "from x\[y\] \(value of map put\) at escape_because.go:93$" "leaking param: y$" "leaking param: z$" - x[y] = z - return z -} - -func f11(x map[*int]*int, y, z *int) map[*int]*int { // ERROR "f11 x does not escape$" "from map\[\*int\]\*int literal \(map literal key\) at escape_because.go:98$" "from map\[\*int\]\*int literal \(map literal value\) at escape_because.go:98$" "leaking param: y$" "leaking param: z$" - return map[*int]*int{y: z} // ERROR "from ~r3 \(return\) at escape_because.go:98$" "map\[\*int\]\*int literal escapes to heap$" -} - -func f12() { - b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from b \(assigned\) at escape_because.go:102$" "from b \(passed to call\[argument escapes\]\) at escape_because.go:103$" - escape(b) -} - -func escape(b []byte) { // ERROR "from panic\(b\) \(panic\) at escape_because.go:107$" "leaking param: b$" - panic(b) -} - -func f13() { - b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:112$" "from b \(assigned\) at escape_because.go:111$" "from c \(assigned\) at escape_because.go:112$" "from c \(passed to call\[argument escapes\]\) at escape_because.go:113$" - c := transmit(b) - escape(c) -} - -func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because.go:117$" "leaking param: b to result ~r1 level=0$" - return b -} - -func f14() { - n := 32 - s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap" "from make\(\[\]int, n\) \(non-constant size\)" - s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap" "from make\(\[\]int, 0, n\) \(non-constant size\)" - _, _ = s1, s2 -} - -func leakParams(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2 level=0$" "from ~r2 \(return\) at escape_because.go:128$" "leaking param: p2 to result ~r3 level=0$" "from ~r3 \(return\) at escape_because.go:128$" - return p1, p2 -} - -func leakThroughOAS2() { - // See #26987. - i := 0 // ERROR "moved to heap: i$" - j := 0 // ERROR "moved to heap: j$" - sink, sink = &i, &j // ERROR "&i escapes to heap$" "from sink \(assign-pair\) at escape_because.go:135$" "&j escapes to heap$" -} - -func leakThroughOAS2FUNC() { - // See #26987. - i := 0 // ERROR "moved to heap: i$" - j := 0 - sink, _ = leakParams(&i, &j) -} - -// The list below is all of the why-escapes messages seen building the escape analysis tests. -/* - for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done - grep 'from .* at ' escape*.log | sed -e 's/^.*(\([^()]*\))[^()]*$/\1/' | sort -u -*/ -// sed RE above assumes that (reason) is the last parenthesized phrase in the line, -// and that none of the reasons contains any parentheses - -/* -... arg to recursive call -address-of -appended slice... -appended to slice -appendee slice -arg to ... -arg to recursive call -array-element-equals -array literal element -assigned -assigned to top level variable -assign-pair-dot-type -assign-pair-func-call -captured by a closure -captured by called closure -dot -dot-equals -dot of pointer -fixed-array-index-of -go func arg -indirection -interface-converted -key of map put -map literal key -map literal value -non-constant size -panic -parameter to indirect call -passed-to-and-returned-from-call -passed to call[argument content escapes] -passed to call[argument escapes] -pointer literal -range-deref -receiver in indirect call -return -returned from recursive function -slice-element-equals -slice-literal-element -star-dot-equals -star-equals -struct literal element -too large for stack -value of map put -*/ - -// Expected, but not yet seen (they may be unreachable): - -/* -append-first-arg -assign-pair-mapr -assign-pair-receive -call receiver -map index -pointer literal [assign] -slice literal element -*/ diff --git a/test/escape_calls.go b/test/escape_calls.go index 53f14dffd3..7b1862e014 100644 --- a/test/escape_calls.go +++ b/test/escape_calls.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_closure.go b/test/escape_closure.go index cf055d3b34..57aabc5b55 100644 --- a/test/escape_closure.go +++ b/test/escape_closure.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_field.go b/test/escape_field.go index 5d5a6f36b4..7291f94e50 100644 --- a/test/escape_field.go +++ b/test/escape_field.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_iface.go b/test/escape_iface.go index 50c69cd5c1..9faabff4b5 100644 --- a/test/escape_iface.go +++ b/test/escape_iface.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_param.go b/test/escape_param.go index 2097556744..76801aa08b 100644 --- a/test/escape_param.go +++ b/test/escape_param.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/escape_struct_return.go b/test/escape_struct_return.go index 2b6de1c76a..222ef8bc22 100644 --- a/test/escape_struct_return.go +++ b/test/escape_struct_return.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/issue12006.go b/test/fixedbugs/issue12006.go index adbbb28b1b..fc95ad1353 100644 --- a/test/fixedbugs/issue12006.go +++ b/test/fixedbugs/issue12006.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -newescape=true +// errorcheck -0 -m -l // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/issue17318.go b/test/fixedbugs/issue17318.go index f875517542..6932d04d25 100644 --- a/test/fixedbugs/issue17318.go +++ b/test/fixedbugs/issue17318.go @@ -1,4 +1,4 @@ -// errorcheck -0 -N -m -l -newescape=true +// errorcheck -0 -N -m -l // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/issue27732a.go b/test/fixedbugs/issue27732a.go index 41b62a6d88..2d0198da0e 100644 --- a/test/fixedbugs/issue27732a.go +++ b/test/fixedbugs/issue27732a.go @@ -1,4 +1,4 @@ -// errorcheck -0 -m -l -smallframes -newescape=true +// errorcheck -0 -m -l -smallframes // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/fixedbugs/oldescape_issue12006.go b/test/fixedbugs/oldescape_issue12006.go deleted file mode 100644 index 0697f58b64..0000000000 --- a/test/fixedbugs/oldescape_issue12006.go +++ /dev/null @@ -1,174 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 through ... parameters. - -package foo - -func FooN(vals ...*int) (s int) { // ERROR "FooN vals does not escape" - for _, v := range vals { - s += *v - } - return s -} - -// Append forces heap allocation and copies entries in vals to heap, therefore they escape to heap. -func FooNx(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param content: vals" - vals = append(vals, x) - return FooN(vals...) -} - -var sink []*int - -func FooNy(x *int, vals ...*int) (s int) { // ERROR "leaking param: x" "leaking param: vals" "leaking param content: vals" - vals = append(vals, x) - sink = vals - return FooN(vals...) -} - -func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals" - sink = vals - return FooN(vals...) -} - -func TFooN() { - for i := 0; i < 1000; i++ { - var i, j int - FooN(&i, &j) // ERROR "TFooN ... argument does not escape" - } -} - -func TFooNx() { - for i := 0; i < 1000; i++ { - var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k" - FooNx(&k, &i, &j) // ERROR "TFooNx ... argument does not escape" - } -} - -func TFooNy() { - for i := 0; i < 1000; i++ { - var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k" - FooNy(&k, &i, &j) // ERROR "... argument escapes to heap" - } -} - -func TFooNz() { - for i := 0; i < 1000; i++ { - var i, j int // ERROR "moved to heap: i" "moved to heap: j" - FooNz(&i, &j) // ERROR "... argument escapes to heap" - } -} - -var isink *int32 - -func FooI(args ...interface{}) { // ERROR "leaking param content: args" - for i := 0; i < len(args); i++ { - switch x := args[i].(type) { - case nil: - println("is nil") - case int32: - println("is int32") - case *int32: - println("is *int32") - isink = x - case string: - println("is string") - } - } -} - -func TFooI() { - a := int32(1) // ERROR "moved to heap: a" - b := "cat" - c := &a - FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape" -} - -func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1" - for i := 0; i < len(args); i++ { - switch x := args[i].(type) { - case nil: - println("is nil") - case int32: - println("is int32") - case *int32: - println("is *int32") - return x - case string: - println("is string") - } - } - return nil -} - -func TFooJ1() { - a := int32(1) - b := "cat" - c := &a - FooJ(a, b, c) // ERROR "TFooJ1 a does not escape" "TFooJ1 b does not escape" "TFooJ1 c does not escape" "TFooJ1 ... argument does not escape" -} - -func TFooJ2() { - a := int32(1) // ERROR "moved to heap: a" - b := "cat" - c := &a - isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... argument does not escape" -} - -type fakeSlice struct { - l int - a *[4]interface{} -} - -func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 level=1" - for i := 0; i < args.l; i++ { - switch x := (*args.a)[i].(type) { - case nil: - println("is nil") - case int32: - println("is int32") - case *int32: - println("is *int32") - return x - case string: - println("is string") - } - } - return nil -} - -func TFooK2() { - a := int32(1) // ERROR "moved to heap: a" - b := "cat" - c := &a - fs := fakeSlice{3, &[4]interface{}{a, b, c, nil}} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooK2 &\[4\]interface {} literal does not escape" - isink = FooK(fs) -} - -func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~r1 level=1" - for i := 0; i < len(args); i++ { - switch x := args[i].(type) { - case nil: - println("is nil") - case int32: - println("is int32") - case *int32: - println("is *int32") - return x - case string: - println("is string") - } - } - return nil -} - -func TFooL2() { - a := int32(1) // ERROR "moved to heap: a" - b := "cat" - c := &a - s := []interface{}{a, b, c} // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooL2 \[\]interface {} literal does not escape" - isink = FooL(s) -} diff --git a/test/fixedbugs/oldescape_issue17318.go b/test/fixedbugs/oldescape_issue17318.go deleted file mode 100644 index 10084ba812..0000000000 --- a/test/fixedbugs/oldescape_issue17318.go +++ /dev/null @@ -1,47 +0,0 @@ -// errorcheck -0 -N -m -l -newescape=false - -// Copyright 2016 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. - -// The escape analyzer needs to run till its root set settles -// (this is not that often, it turns out). -// This test is likely to become stale because the leak depends -// on a spurious-escape bug -- return an interface as a named -// output parameter appears to cause the called closure to escape, -// where returning it as a regular type does not. - -package main - -import ( - "fmt" -) - -type closure func(i, j int) ent - -type ent int - -func (e ent) String() string { - return fmt.Sprintf("%d", int(e)) // ERROR "ent.String ... argument does not escape$" "int\(e\) escapes to heap$" -} - -//go:noinline -func foo(ops closure, j int) (err fmt.Stringer) { // ERROR "leaking param: ops$" "leaking param: ops to result err level=0$" - enqueue := func(i int) fmt.Stringer { // ERROR "func literal escapes to heap$" - return ops(i, j) // ERROR "ops\(i, j\) escapes to heap$" - } - err = enqueue(4) - if err != nil { - return err - } - return // return result of enqueue, a fmt.Stringer -} - -func main() { - // 3 identical functions, to get different escape behavior. - f := func(i, j int) ent { // ERROR "func literal escapes to heap$" - return ent(i + j) - } - i := foo(f, 3).(ent) - fmt.Printf("foo(f,3)=%d\n", int(i)) // ERROR "int\(i\) escapes to heap$" "main ... argument does not escape$" -} diff --git a/test/linkname.go b/test/linkname.go index 8e79b51b9b..c94a113c90 100644 --- a/test/linkname.go +++ b/test/linkname.go @@ -1,4 +1,4 @@ -// errorcheckandrundir -0 -m -l=4 -newescape=true +// errorcheckandrundir -0 -m -l=4 // Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/test/oldescape2.go b/test/oldescape2.go deleted file mode 100644 index 864a956164..0000000000 --- a/test/oldescape2.go +++ /dev/null @@ -1,1847 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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. - -// Test, using compiler diagnostic flags, that the escape analysis is working. -// Compiles but does not run. Inlining is disabled. - -// escape2n.go contains all the same tests but compiles with -N. - -package foo - -import ( - "fmt" - "unsafe" -) - -var gxx *int - -func foo1(x int) { // ERROR "moved to heap: x$" - gxx = &x -} - -func foo2(yy *int) { // ERROR "leaking param: yy$" - gxx = yy -} - -func foo3(x int) *int { // ERROR "moved to heap: x$" - return &x -} - -type T *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 "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 "foo5 xx does not escape$" "foo5 yy does not escape$" - xx = &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 "foo7 xx does not escape$" "foo7 yy does not escape$" - **xx = *yy -} - -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 to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$" - xx = yy - return xx -} - -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 - yy := &y - *xx = *yy - return x -} - -var xxx **int - -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 content: yyy$" - *xxx = *yyy -} - -func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$" - **xxx = **yyy -} - -func foo15(yy *int) { // ERROR "moved to heap: yy$" - xxx = &yy -} - -func foo16(yy *int) { // ERROR "leaking param: yy$" - *xxx = yy -} - -func foo17(yy *int) { // ERROR "foo17 yy does not escape$" - **xxx = *yy -} - -func foo18(y int) { // ERROR "moved to heap: y$" - *xxx = &y -} - -func foo19(y int) { - **xxx = y -} - -type Bar struct { - i int - ii *int -} - -func NewBar() *Bar { - return &Bar{42, nil} // 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 "NewBarp2 x does not escape$" - return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$" -} - -func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$" - return *(b.ii) -} - -func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$" - return &b.i -} - -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 to result ~r0 level=0$" - return b.ii -} - -func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$" - v := 0 // ERROR "moved to heap: v$" - b.ii = &v - return b.ii -} - -func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$" - v := 0 // ERROR "moved to heap: v$" - b.ii = &v - return b.ii -} - -func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$" - v := 0 - b.ii = &v - return b.i -} - -func goLeak(b *Bar) { // ERROR "leaking param: b$" - go b.NoLeak() -} - -type Bar2 struct { - i [12]int - ii []int -} - -func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$" -} - -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 to result ~r0 level=0$" - return b.i[:] -} - -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 "Bar2.AgainNoLeak b does not escape$" - return b.i -} - -func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$" - b.ii = b.i[0:4] -} - -func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$" - var buf []int - buf = b.i[0:] - b.ii = buf -} - -func foo21() func() int { - 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++ - return x - } -} - -func foo22() int { - x := 42 - return func() int { // ERROR "foo22 func literal does not escape$" - return x - }() -} - -func foo23(x int) func() int { - return func() int { // ERROR "func literal escapes to heap$" - return x - } -} - -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) { - f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$" - return &f -} - -func foo23c(x int) func() int { // ERROR "moved to heap: x$" - return func() int { // ERROR "func literal escapes to heap$" - x++ - return x - } -} - -func foo24(x int) int { - return func() int { // ERROR "foo24 func literal does not escape$" - return x - }() -} - -var x *int - -func fooleak(xx *int) int { // ERROR "leaking param: xx$" - x = xx - return *x -} - -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) -} - -func foo32(x int) int { - return foonoleak(&x) -} - -type Foo struct { - xx *int - x int -} - -var F Foo -var pf *Foo - -func (f *Foo) fooleak() { // ERROR "leaking param: f$" - pf = f -} - -func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$" - F.x = f.x -} - -func (f *Foo) Leak() { // ERROR "leaking param: f$" - f.fooleak() -} - -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 -} - -func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$" - f.xx = &x -} - -func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$" - f.xx = &x -} - -func foo44(yy *int) { // ERROR "leaking param: yy$" - F.xx = yy -} - -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 content: f$" - F.xx = f.xx -} - -func (f *Foo) foo47() { // ERROR "leaking param: f$" - f.xx = &f.x -} - -var ptrSlice []*int - -func foo50(i *int) { // ERROR "leaking param: i$" - ptrSlice[0] = i -} - -var ptrMap map[*int]*int - -func foo51(i *int) { // ERROR "leaking param: i$" - ptrMap[i] = i -} - -func indaddr1(x int) *int { // ERROR "moved to heap: x$" - return &x -} - -func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" - return *&x -} - -func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$" - return *(**int)(unsafe.Pointer(&x)) -} - -// From package math: - -func Float32bits(f float32) uint32 { - return *(*uint32)(unsafe.Pointer(&f)) -} - -func Float32frombits(b uint32) float32 { - return *(*float32)(unsafe.Pointer(&b)) -} - -func Float64bits(f float64) uint64 { - return *(*uint64)(unsafe.Pointer(&f)) -} - -func Float64frombits(b uint64) float64 { - return *(*float64)(unsafe.Pointer(&b)) -} - -// contrast with -func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$" - return (*uint64)(unsafe.Pointer(&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 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 - } - return nil -} - -func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" - 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: i to result ~r1 level=0$" - var a [12]*int - a[0] = i - return a[1] -} - -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 to result ~r1 level=0$" - type S struct { - a, b *int - } - var s S - s.a = i - return s.b -} - -func foo61a(i *int) *int { // ERROR "foo61a 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: i$" - type S struct { - a, b *int - } - s := new(S) // ERROR "foo62 new\(S\) does not escape$" - s.a = i - return nil // s.b -} - -type M interface { - M() -} - -func foo63(m M) { // ERROR "foo63 m does not escape$" -} - -func foo64(m M) { // ERROR "leaking param: m$" - m.M() -} - -func foo64b(m M) { // ERROR "leaking param: m$" - defer m.M() -} - -type MV int - -func (MV) M() {} - -func foo65() { - var mv MV - 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$" -} - -func foo67() { - var mv MV - foo63(mv) // ERROR "foo67 mv does not escape$" -} - -func foo68() { - var mv MV - // escapes but it's an int so irrelevant - foo64(mv) // ERROR "mv escapes to heap$" -} - -func foo69(m M) { // ERROR "leaking param: m$" - foo64(m) -} - -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$" - var y []*int - y = append(y, x) - return y -} - -func foo71a(x int) []*int { // ERROR "moved to heap: x$" - var y []*int - y = append(y, &x) - return y -} - -func foo72() { - var x int - var y [1]*int - y[0] = &x -} - -func foo72aa() [10]*int { - var x int // ERROR "moved to heap: x$" - var y [10]*int - y[0] = &x - return y -} - -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 - } - return -} - -func foo72b() [10]*int { - var y [10]*int - for i := 0; i < 10; i++ { - x := i // ERROR "moved to heap: x$" - y[i] = &x - } - return y -} - -// issue 2145 -func foo73() { - 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$" - // actually just escapes its scope - defer func() { // ERROR "func literal escapes to heap$" - vv = 42 - println(vv) - }() - } -} - -func foo74() { - s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$" - for _, v := range s { - vv := v - // actually just escapes its scope - 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 - println(vv) - } - defer fn() - } -} - -// issue 3975 -func foo74b() { - var array [3]func() - s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$" - for i, v := range s { - vv := v - // actually just escapes its scope - array[i] = func() { // ERROR "func literal escapes to heap$" - println(vv) - } - } -} - -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) - } - } -} - -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 "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$" - return &x[0] -} - -func foo75(z *int) { // ERROR "foo75 z does not escape$" - myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$" -} - -func foo75a(z *int) { // ERROR "foo75a z does not escape$" - myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$" -} - -func foo75esc(z *int) { // ERROR "leaking param: z$" - gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument 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$" "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 "z does not escape" - myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape" -} - -func foo76a(z *int) { // ERROR "z does not escape" - myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape" -} - -func foo76b() { - myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$" -} - -func foo76c() { - myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$" -} - -func foo76d() { - defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$" -} - -func foo76e() { - defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "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$" "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$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" - } -} - -func foo77(z []interface{}) { // ERROR "foo77 z does not escape$" - myprint(nil, z...) // 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$" - var ppi **interface{} - *ppi = myprint1(nil, z...) -} - -func foo77c(z []interface{}) { // ERROR "leaking param: z$" - sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$" -} - -func dotdotdot() { - i := 0 - myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$" - - j := 0 - myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$" -} - -func foo78(z int) *int { // ERROR "moved to heap: z$" - return &z -} - -func foo78a(z int) *int { // ERROR "moved to heap: z$" - y := &z - x := &y - 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 "foo81 new\(int\) does not escape$" - _ = z - } - return nil -} - -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 "noop x does not escape$" "noop y does not escape$" - -func foo82() { - var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$" - go noop(tee(&z)) - go noop(&x, &y) - for { - var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$" - defer noop(tee(&u)) - defer noop(&v, &w) - } -} - -type Fooer interface { - Foo() -} - -type LimitedFooer struct { - Fooer - N int64 -} - -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 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 to result ~r1 level=0$" - return [2]*int{x, nil} -} - -// does not leak c -func foo93(c chan *int) *int { // ERROR "foo93 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 "leaking param: m to result ~r2 level=1" - 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 "foo95 m does not escape$" "leaking param: x$" - m[x] = x -} - -// 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 to result ~r1 level=0$" - return m[0] -} - -// does not leak m -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 to result ~r1 level=0$" - return m[:] -} - -// does not leak m -func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" - for _, v := range m { - return v - } - return nil -} - -// does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" - for _, v := range m { - return v - } - return nil -} - -// does not leak m -func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$" - for i := range m { // ERROR "moved to heap: i$" - return &i - } - return nil -} - -// does leak 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 "foo103 m does not escape$" "foo103 x does not escape$" - m[0] = x -} - -var y []*int - -// does not leak x but does leak content -func foo104(x []*int) { // ERROR "leaking param content: x" - copy(y, x) -} - -// 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$" - _ = append(y, x) -} - -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\[\*int\]\*int literal escapes to heap$" -} - -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 "foo110 map\[\*int\]\*int literal does not escape$" - return m[nil] -} - -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 to result ~r1 level=0$" - m := [1]*int{x} - return m[0] -} - -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 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 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 - } else { - y := 1 // ERROR "moved to heap: y$" - return &y - } - return nil -} - -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 "foo118 unknown does not escape$" - x := 1 // ERROR "moved to heap: x$" - unknown(&x) -} - -func external(*int) - -func foo119(x *int) { // ERROR "leaking param: x$" - external(x) -} - -func foo120() { - // formerly exponential time analysis -L1: -L2: -L3: -L4: -L5: -L6: -L7: -L8: -L9: -L10: -L11: -L12: -L13: -L14: -L15: -L16: -L17: -L18: -L19: -L20: -L21: -L22: -L23: -L24: -L25: -L26: -L27: -L28: -L29: -L30: -L31: -L32: -L33: -L34: -L35: -L36: -L37: -L38: -L39: -L40: -L41: -L42: -L43: -L44: -L45: -L46: -L47: -L48: -L49: -L50: -L51: -L52: -L53: -L54: -L55: -L56: -L57: -L58: -L59: -L60: -L61: -L62: -L63: -L64: -L65: -L66: -L67: -L68: -L69: -L70: -L71: -L72: -L73: -L74: -L75: -L76: -L77: -L78: -L79: -L80: -L81: -L82: -L83: -L84: -L85: -L86: -L87: -L88: -L89: -L90: -L91: -L92: -L93: -L94: -L95: -L96: -L97: -L98: -L99: -L100: - // use the labels to silence compiler errors - goto L1 - goto L2 - goto L3 - goto L4 - goto L5 - goto L6 - goto L7 - goto L8 - goto L9 - goto L10 - goto L11 - goto L12 - goto L13 - goto L14 - goto L15 - goto L16 - goto L17 - goto L18 - goto L19 - goto L20 - goto L21 - goto L22 - goto L23 - goto L24 - goto L25 - goto L26 - goto L27 - goto L28 - goto L29 - goto L30 - goto L31 - goto L32 - goto L33 - goto L34 - goto L35 - goto L36 - goto L37 - goto L38 - goto L39 - goto L40 - goto L41 - goto L42 - goto L43 - goto L44 - goto L45 - goto L46 - goto L47 - goto L48 - goto L49 - goto L50 - goto L51 - goto L52 - goto L53 - goto L54 - goto L55 - goto L56 - goto L57 - goto L58 - goto L59 - goto L60 - goto L61 - goto L62 - goto L63 - goto L64 - goto L65 - goto L66 - goto L67 - goto L68 - goto L69 - goto L70 - goto L71 - goto L72 - goto L73 - goto L74 - goto L75 - goto L76 - goto L77 - goto L78 - goto L79 - goto L80 - goto L81 - goto L82 - goto L83 - goto L84 - goto L85 - goto L86 - goto L87 - goto L88 - goto L89 - goto L90 - goto L91 - goto L92 - goto L93 - goto L94 - goto L95 - goto L96 - goto L97 - goto L98 - goto L99 - goto L100 -} - -func foo121() { - for i := 0; i < 10; i++ { - 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$" "i escapes to heap$" - go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - } -} - -// a harmless forward jump -func foo122() { - var i *int - - goto L1 -L1: - i = new(int) // ERROR "foo122 new\(int\) does not escape$" - _ = i -} - -// a backward jump, increases loopdepth -func foo123() { - var i *int - -L1: - i = new(int) // ERROR "new\(int\) escapes to heap$" - - goto L1 - _ = i -} - -func foo124(x **int) { // ERROR "foo124 x does not escape$" - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo124 func literal does not escape$" - *x = p - }() -} - -func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$" - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo125 func literal does not escape$" - ch <- p - }() -} - -func foo126() { - var px *int // loopdepth 0 - for { - // loopdepth 1 - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo126 func literal does not escape$" - px = &i - }() - } - _ = px -} - -var px *int - -func foo127() { - var i int // ERROR "moved to heap: i$" - p := &i - q := p - px = q -} - -func foo128() { - var i int - p := &i - q := p - _ = q -} - -func foo129() { - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo129 func literal does not escape$" - q := p - func() { // ERROR "foo129.func1 func literal does not escape$" - r := q - px = r - }() - }() -} - -func foo130() { - for { - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo130 func literal does not escape$" - px = &i - }() - } -} - -func foo131() { - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo131 func literal does not escape$" - px = &i - }() -} - -func foo132() { - var i int // ERROR "moved to heap: i$" - go func() { // ERROR "func literal escapes to heap$" - px = &i - }() -} - -func foo133() { - var i int // ERROR "moved to heap: i$" - defer func() { // ERROR "foo133 func literal does not escape$" - px = &i - }() -} - -func foo134() { - var i int - p := &i - func() { // ERROR "foo134 func literal does not escape$" - q := p - func() { // ERROR "foo134.func1 func literal does not escape$" - r := q - _ = r - }() - }() -} - -func foo135() { - var i int // ERROR "moved to heap: i$" - p := &i - go func() { // ERROR "func literal escapes to heap$" - q := p - func() { // ERROR "foo135.func1 func literal does not escape$" - r := q - _ = r - }() - }() -} - -func foo136() { - var i int // ERROR "moved to heap: i$" - p := &i - go func() { // ERROR "func literal escapes to heap$" - q := p - func() { // ERROR "foo136.func1 func literal does not escape$" - r := q - px = r - }() - }() -} - -func foo137() { - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo137 func literal does not escape$" - q := p - go func() { // ERROR "func literal escapes to heap$" - r := q - _ = r - }() - }() -} - -func foo138() *byte { - type T struct { - x [1]byte - } - t := new(T) // ERROR "new\(T\) escapes to heap$" - return &t.x[0] -} - -func foo139() *byte { - type T struct { - x struct { - y byte - } - } - t := new(T) // ERROR "new\(T\) escapes to heap$" - return &t.x.y -} - -// issue 4751 -func foo140() interface{} { - type T struct { - X string - } - type U struct { - X string - T *T - } - t := &T{} // ERROR "&T literal escapes to heap$" - return U{ // ERROR "U literal escapes to heap$" - X: t.X, - T: t, - } -} - -//go:noescape - -func F1([]byte) - -func F2([]byte) - -//go:noescape - -func F3(x []byte) // ERROR "F3 x does not escape$" - -func F4(x []byte) - -func G() { - var buf1 [10]byte - F1(buf1[:]) - - var buf2 [10]byte // ERROR "moved to heap: buf2$" - F2(buf2[:]) - - var buf3 [10]byte - F3(buf3[:]) - - var buf4 [10]byte // ERROR "moved to heap: buf4$" - F4(buf4[:]) -} - -type Tm struct { - x int -} - -func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$" -} - -func foo141() { - var f func() - - 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 "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 "foo143 func literal does not escape$" - for i := 0; i < 1; i++ { - var t Tm - t.M() - } - }() - } -} - -// issue 5773 -// Check that annotations take effect regardless of whether they -// are before or after the use in the source code. - -//go:noescape - -func foo144a(*int) - -func foo144() { - var x int - foo144a(&x) - var y int - foo144b(&y) -} - -//go:noescape - -func foo144b(*int) - -// issue 7313: for loop init should not be treated as "in loop" - -type List struct { - Next *List -} - -func foo145(l List) { // ERROR "foo145 l does not escape$" - var p *List - for p = &l; p.Next != nil; p = p.Next { - } -} - -func foo146(l List) { // ERROR "foo146 l does not escape$" - var p *List - p = &l - for ; p.Next != nil; p = p.Next { - } -} - -func foo147(l List) { // ERROR "foo147 l does not escape$" - var p *List - p = &l - for p.Next != nil { - p = p.Next - } -} - -func foo148(l List) { // ERROR "foo148 l does not escape$" - for p := &l; p.Next != nil; p = p.Next { - } -} - -// related: address of variable should have depth of variable, not of loop - -func foo149(l List) { // ERROR "foo149 l does not escape$" - var p *List - for { - for p = &l; p.Next != nil; p = p.Next { - } - } -} - -// issue 7934: missed ... if element type had no pointers - -var save150 []byte - -func foo150(x ...byte) { // ERROR "leaking param: x$" - save150 = x -} - -func bar150() { - 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$" - save151 = x -} - -func bar151() { - var a [64]int // ERROR "moved to heap: a$" - a[4] = 101 - foo151(&(&a)[4:8][0]) -} - -func bar151b() { - var a [10]int // ERROR "moved to heap: a$" - b := a[:] - foo151(&b[4:8][0]) -} - -func bar151c() { - var a [64]int // ERROR "moved to heap: a$" - a[4] = 101 - foo151(&(&a)[4:8:8][0]) -} - -func bar151d() { - var a [10]int // ERROR "moved to heap: a$" - b := a[:] - foo151(&b[4:8:8][0]) -} - -// issue 8120 - -type U struct { - s *string -} - -func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$" - return u.s -} - -type V struct { - s *string -} - -// 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$" -} - -func foo152() { - a := "a" // ERROR "moved to heap: a$" - u := U{&a} - 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 to result ~r1 level=-1$" - switch x := v.(type) { - case int: // ERROR "moved to heap: x$" - return &x - } - panic(0) -} - -// issue 8185 - &result escaping into result - -func f() (x int, y *int) { // ERROR "moved to heap: x$" - y = &x - return -} - -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$" - _ = x -} - -func ptrlitNoEscape2() { - // Literal does not escape, but element does. - i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "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$" - sink = x // ERROR "x escapes to heap$" -} - -// self-assignments - -type Buffer struct { - arr [64]byte - arrPtr *[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 in b.buf1 = b.buf1\[1:2\]$" - b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2:3\]$" - b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2\]$" - b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2:3\]$" -} - -func (b *Buffer) bar() { // ERROR "leaking param: b$" - b.buf1 = b.arr[1:2] -} - -func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape" - b.buf1 = b.arrPtr[1:2] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2\]$" - b.buf1 = b.arrPtr[1:2:3] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2:3\]$" -} - -func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$" - b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str1\[1:2\]$" - b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str2\[1:2\]$" -} - -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 in \*sp = \(\*sp\)\[1:2\]$" - *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment in \*bp = \(\*bp\)\[1:2\]$" -} - -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 - 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] -} - -func issue12397(x, y int) { // ERROR "moved to heap: y$" - // x does not escape below, because all relevant code is dead. - if false { - gxx = &x - } else { - gxx = &y - } - - if true { - gxx = &y - } else { - gxx = &x - } -} diff --git a/test/oldescape2n.go b/test/oldescape2n.go deleted file mode 100644 index fb2a956618..0000000000 --- a/test/oldescape2n.go +++ /dev/null @@ -1,1847 +0,0 @@ -// errorcheck -0 -N -m -l -newescape=false - -// 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. - -// Test, using compiler diagnostic flags, that the escape analysis is working. -// Compiles but does not run. Inlining is disabled. -// Registerization is disabled too (-N), which should -// have no effect on escape analysis. - -package foo - -import ( - "fmt" - "unsafe" -) - -var gxx *int - -func foo1(x int) { // ERROR "moved to heap: x$" - gxx = &x -} - -func foo2(yy *int) { // ERROR "leaking param: yy$" - gxx = yy -} - -func foo3(x int) *int { // ERROR "moved to heap: x$" - return &x -} - -type T *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 "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 "foo5 xx does not escape$" "foo5 yy does not escape$" - xx = &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 "foo7 xx does not escape$" "foo7 yy does not escape$" - **xx = *yy -} - -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 to result ~r2 level=0$" "leaking param: yy to result ~r2 level=0$" - xx = yy - return xx -} - -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 - yy := &y - *xx = *yy - return x -} - -var xxx **int - -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 content: yyy$" - *xxx = *yyy -} - -func foo14(yyy **int) { // ERROR "foo14 yyy does not escape$" - **xxx = **yyy -} - -func foo15(yy *int) { // ERROR "moved to heap: yy$" - xxx = &yy -} - -func foo16(yy *int) { // ERROR "leaking param: yy$" - *xxx = yy -} - -func foo17(yy *int) { // ERROR "foo17 yy does not escape$" - **xxx = *yy -} - -func foo18(y int) { // ERROR "moved to heap: y$" - *xxx = &y -} - -func foo19(y int) { - **xxx = y -} - -type Bar struct { - i int - ii *int -} - -func NewBar() *Bar { - return &Bar{42, nil} // 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 "NewBarp2 x does not escape$" - return &Bar{*x, nil} // ERROR "&Bar literal escapes to heap$" -} - -func (b *Bar) NoLeak() int { // ERROR "\(\*Bar\).NoLeak b does not escape$" - return *(b.ii) -} - -func (b *Bar) Leak() *int { // ERROR "leaking param: b to result ~r0 level=0$" - return &b.i -} - -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 to result ~r0 level=0$" - return b.ii -} - -func (b Bar) LeaksToo() *int { // ERROR "leaking param: b to result ~r0 level=0$" - v := 0 // ERROR "moved to heap: v$" - b.ii = &v - return b.ii -} - -func (b *Bar) LeaksABit() *int { // ERROR "leaking param: b to result ~r0 level=1$" - v := 0 // ERROR "moved to heap: v$" - b.ii = &v - return b.ii -} - -func (b Bar) StillNoLeak() int { // ERROR "Bar.StillNoLeak b does not escape$" - v := 0 - b.ii = &v - return b.i -} - -func goLeak(b *Bar) { // ERROR "leaking param: b$" - go b.NoLeak() -} - -type Bar2 struct { - i [12]int - ii []int -} - -func NewBar2() *Bar2 { - return &Bar2{[12]int{42}, nil} // ERROR "&Bar2 literal escapes to heap$" -} - -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 to result ~r0 level=0$" - return b.i[:] -} - -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 "Bar2.AgainNoLeak b does not escape$" - return b.i -} - -func (b *Bar2) LeakSelf() { // ERROR "leaking param: b$" - b.ii = b.i[0:4] -} - -func (b *Bar2) LeakSelf2() { // ERROR "leaking param: b$" - var buf []int - buf = b.i[0:] - b.ii = buf -} - -func foo21() func() int { - 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++ - return x - } -} - -func foo22() int { - x := 42 - return func() int { // ERROR "foo22 func literal does not escape$" - return x - }() -} - -func foo23(x int) func() int { - return func() int { // ERROR "func literal escapes to heap$" - return x - } -} - -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) { - f := func() int { return x } // ERROR "func literal escapes to heap$" "moved to heap: f$" - return &f -} - -func foo23c(x int) func() int { // ERROR "moved to heap: x$" - return func() int { // ERROR "func literal escapes to heap$" - x++ - return x - } -} - -func foo24(x int) int { - return func() int { // ERROR "foo24 func literal does not escape$" - return x - }() -} - -var x *int - -func fooleak(xx *int) int { // ERROR "leaking param: xx$" - x = xx - return *x -} - -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) -} - -func foo32(x int) int { - return foonoleak(&x) -} - -type Foo struct { - xx *int - x int -} - -var F Foo -var pf *Foo - -func (f *Foo) fooleak() { // ERROR "leaking param: f$" - pf = f -} - -func (f *Foo) foonoleak() { // ERROR "\(\*Foo\).foonoleak f does not escape$" - F.x = f.x -} - -func (f *Foo) Leak() { // ERROR "leaking param: f$" - f.fooleak() -} - -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 -} - -func (f *Foo) foo42(x int) { // ERROR "\(\*Foo\).foo42 f does not escape$" "moved to heap: x$" - f.xx = &x -} - -func foo43(f *Foo, x int) { // ERROR "foo43 f does not escape$" "moved to heap: x$" - f.xx = &x -} - -func foo44(yy *int) { // ERROR "leaking param: yy$" - F.xx = yy -} - -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 content: f$" - F.xx = f.xx -} - -func (f *Foo) foo47() { // ERROR "leaking param: f$" - f.xx = &f.x -} - -var ptrSlice []*int - -func foo50(i *int) { // ERROR "leaking param: i$" - ptrSlice[0] = i -} - -var ptrMap map[*int]*int - -func foo51(i *int) { // ERROR "leaking param: i$" - ptrMap[i] = i -} - -func indaddr1(x int) *int { // ERROR "moved to heap: x$" - return &x -} - -func indaddr2(x *int) *int { // ERROR "leaking param: x to result ~r1 level=0$" - return *&x -} - -func indaddr3(x *int32) *int { // ERROR "leaking param: x to result ~r1 level=0$" - return *(**int)(unsafe.Pointer(&x)) -} - -// From package math: - -func Float32bits(f float32) uint32 { - return *(*uint32)(unsafe.Pointer(&f)) -} - -func Float32frombits(b uint32) float32 { - return *(*float32)(unsafe.Pointer(&b)) -} - -func Float64bits(f float64) uint64 { - return *(*uint64)(unsafe.Pointer(&f)) -} - -func Float64frombits(b uint64) float64 { - return *(*float64)(unsafe.Pointer(&b)) -} - -// contrast with -func float64bitsptr(f float64) *uint64 { // ERROR "moved to heap: f$" - return (*uint64)(unsafe.Pointer(&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 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 - } - return nil -} - -func exprsw(i *int) *int { // ERROR "leaking param: i to result ~r1 level=0$" - 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: i to result ~r1 level=0$" - var a [12]*int - a[0] = i - return a[1] -} - -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 to result ~r1 level=0$" - type S struct { - a, b *int - } - var s S - s.a = i - return s.b -} - -func foo61a(i *int) *int { // ERROR "foo61a 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: i$" - type S struct { - a, b *int - } - s := new(S) // ERROR "foo62 new\(S\) does not escape$" - s.a = i - return nil // s.b -} - -type M interface { - M() -} - -func foo63(m M) { // ERROR "foo63 m does not escape$" -} - -func foo64(m M) { // ERROR "leaking param: m$" - m.M() -} - -func foo64b(m M) { // ERROR "leaking param: m$" - defer m.M() -} - -type MV int - -func (MV) M() {} - -func foo65() { - var mv MV - 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$" -} - -func foo67() { - var mv MV - foo63(mv) // ERROR "foo67 mv does not escape$" -} - -func foo68() { - var mv MV - // escapes but it's an int so irrelevant - foo64(mv) // ERROR "mv escapes to heap$" -} - -func foo69(m M) { // ERROR "leaking param: m$" - foo64(m) -} - -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$" - var y []*int - y = append(y, x) - return y -} - -func foo71a(x int) []*int { // ERROR "moved to heap: x$" - var y []*int - y = append(y, &x) - return y -} - -func foo72() { - var x int - var y [1]*int - y[0] = &x -} - -func foo72aa() [10]*int { - var x int // ERROR "moved to heap: x$" - var y [10]*int - y[0] = &x - return y -} - -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 - } - return -} - -func foo72b() [10]*int { - var y [10]*int - for i := 0; i < 10; i++ { - x := i // ERROR "moved to heap: x$" - y[i] = &x - } - return y -} - -// issue 2145 -func foo73() { - 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$" - // actually just escapes its scope - defer func() { // ERROR "func literal escapes to heap$" - vv = 42 - println(vv) - }() - } -} - -func foo74() { - s := []int{3, 2, 1} // ERROR "foo74 \[\]int literal does not escape$" - for _, v := range s { - vv := v - // actually just escapes its scope - 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 - println(vv) - } - defer fn() - } -} - -// issue 3975 -func foo74b() { - var array [3]func() - s := []int{3, 2, 1} // ERROR "foo74b \[\]int literal does not escape$" - for i, v := range s { - vv := v - // actually just escapes its scope - array[i] = func() { // ERROR "func literal escapes to heap$" - println(vv) - } - } -} - -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) - } - } -} - -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 "leaking param: x to result ~r2 level=0$" "myprint1 y does not escape$" - return &x[0] -} - -func foo75(z *int) { // ERROR "foo75 z does not escape$" - myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75 ... argument does not escape$" -} - -func foo75a(z *int) { // ERROR "foo75a z does not escape$" - myprint1(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75a ... argument does not escape$" -} - -func foo75esc(z *int) { // ERROR "leaking param: z$" - gxx = myprint(z, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo75esc ... argument 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$" "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 "z does not escape" - myprint(nil, z) // ERROR "foo76 ... argument does not escape$" "z does not escape" -} - -func foo76a(z *int) { // ERROR "z does not escape" - myprint1(nil, z) // ERROR "foo76a ... argument does not escape$" "z does not escape" -} - -func foo76b() { - myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76b ... argument does not escape$" -} - -func foo76c() { - myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76c ... argument does not escape$" -} - -func foo76d() { - defer myprint(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "foo76d ... argument does not escape$" -} - -func foo76e() { - defer myprint1(nil, 1, 2, 3) // ERROR "1 does not escape" "2 does not escape" "3 does not escape" "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$" "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$" "1 escapes to heap$" "2 escapes to heap$" "3 escapes to heap$" - } -} - -func foo77(z []interface{}) { // ERROR "foo77 z does not escape$" - myprint(nil, z...) // 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$" - var ppi **interface{} - *ppi = myprint1(nil, z...) -} - -func foo77c(z []interface{}) { // ERROR "leaking param: z$" - sink = myprint1(nil, z...) // ERROR "myprint1\(nil, z...\) escapes to heap$" -} - -func dotdotdot() { - i := 0 - myprint(nil, &i) // ERROR "&i does not escape" "dotdotdot ... argument does not escape$" - - j := 0 - myprint1(nil, &j) // ERROR "&j does not escape" "dotdotdot ... argument does not escape$" -} - -func foo78(z int) *int { // ERROR "moved to heap: z$" - return &z -} - -func foo78a(z int) *int { // ERROR "moved to heap: z$" - y := &z - x := &y - 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 "foo81 new\(int\) does not escape$" - _ = z - } - return nil -} - -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 "noop x does not escape$" "noop y does not escape$" - -func foo82() { - var x, y, z int // ERROR "moved to heap: x$" "moved to heap: y$" "moved to heap: z$" - go noop(tee(&z)) - go noop(&x, &y) - for { - var u, v, w int // ERROR "moved to heap: u$" "moved to heap: v$" "moved to heap: w$" - defer noop(tee(&u)) - defer noop(&v, &w) - } -} - -type Fooer interface { - Foo() -} - -type LimitedFooer struct { - Fooer - N int64 -} - -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 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 to result ~r1 level=0$" - return [2]*int{x, nil} -} - -// does not leak c -func foo93(c chan *int) *int { // ERROR "foo93 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 "leaking param: m to result ~r2 level=1" - 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 "foo95 m does not escape$" "leaking param: x$" - m[x] = x -} - -// 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 to result ~r1 level=0$" - return m[0] -} - -// does not leak m -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 to result ~r1 level=0$" - return m[:] -} - -// does not leak m -func foo100(m []*int) *int { // ERROR "leaking param: m to result ~r1 level=1" - for _, v := range m { - return v - } - return nil -} - -// does leak m -func foo101(m [1]*int) *int { // ERROR "leaking param: m to result ~r1 level=0$" - for _, v := range m { - return v - } - return nil -} - -// does not leak m -func foo101a(m [1]*int) *int { // ERROR "foo101a m does not escape$" - for i := range m { // ERROR "moved to heap: i$" - return &i - } - return nil -} - -// does leak 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 "foo103 m does not escape$" "foo103 x does not escape$" - m[0] = x -} - -var y []*int - -// does not leak x but does leak content -func foo104(x []*int) { // ERROR "leaking param content: x" - copy(y, x) -} - -// 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$" - _ = append(y, x) -} - -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\[\*int\]\*int literal escapes to heap$" -} - -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 "foo110 map\[\*int\]\*int literal does not escape$" - return m[nil] -} - -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 to result ~r1 level=0$" - m := [1]*int{x} - return m[0] -} - -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 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 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 - } else { - y := 1 // ERROR "moved to heap: y$" - return &y - } - return nil -} - -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 "foo118 unknown does not escape$" - x := 1 // ERROR "moved to heap: x$" - unknown(&x) -} - -func external(*int) - -func foo119(x *int) { // ERROR "leaking param: x$" - external(x) -} - -func foo120() { - // formerly exponential time analysis -L1: -L2: -L3: -L4: -L5: -L6: -L7: -L8: -L9: -L10: -L11: -L12: -L13: -L14: -L15: -L16: -L17: -L18: -L19: -L20: -L21: -L22: -L23: -L24: -L25: -L26: -L27: -L28: -L29: -L30: -L31: -L32: -L33: -L34: -L35: -L36: -L37: -L38: -L39: -L40: -L41: -L42: -L43: -L44: -L45: -L46: -L47: -L48: -L49: -L50: -L51: -L52: -L53: -L54: -L55: -L56: -L57: -L58: -L59: -L60: -L61: -L62: -L63: -L64: -L65: -L66: -L67: -L68: -L69: -L70: -L71: -L72: -L73: -L74: -L75: -L76: -L77: -L78: -L79: -L80: -L81: -L82: -L83: -L84: -L85: -L86: -L87: -L88: -L89: -L90: -L91: -L92: -L93: -L94: -L95: -L96: -L97: -L98: -L99: -L100: - // use the labels to silence compiler errors - goto L1 - goto L2 - goto L3 - goto L4 - goto L5 - goto L6 - goto L7 - goto L8 - goto L9 - goto L10 - goto L11 - goto L12 - goto L13 - goto L14 - goto L15 - goto L16 - goto L17 - goto L18 - goto L19 - goto L20 - goto L21 - goto L22 - goto L23 - goto L24 - goto L25 - goto L26 - goto L27 - goto L28 - goto L29 - goto L30 - goto L31 - goto L32 - goto L33 - goto L34 - goto L35 - goto L36 - goto L37 - goto L38 - goto L39 - goto L40 - goto L41 - goto L42 - goto L43 - goto L44 - goto L45 - goto L46 - goto L47 - goto L48 - goto L49 - goto L50 - goto L51 - goto L52 - goto L53 - goto L54 - goto L55 - goto L56 - goto L57 - goto L58 - goto L59 - goto L60 - goto L61 - goto L62 - goto L63 - goto L64 - goto L65 - goto L66 - goto L67 - goto L68 - goto L69 - goto L70 - goto L71 - goto L72 - goto L73 - goto L74 - goto L75 - goto L76 - goto L77 - goto L78 - goto L79 - goto L80 - goto L81 - goto L82 - goto L83 - goto L84 - goto L85 - goto L86 - goto L87 - goto L88 - goto L89 - goto L90 - goto L91 - goto L92 - goto L93 - goto L94 - goto L95 - goto L96 - goto L97 - goto L98 - goto L99 - goto L100 -} - -func foo121() { - for i := 0; i < 10; i++ { - 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$" "i escapes to heap$" - go fmt.Printf("%d", i) // ERROR "... argument escapes to heap$" "i escapes to heap$" - } -} - -// a harmless forward jump -func foo122() { - var i *int - - goto L1 -L1: - i = new(int) // ERROR "foo122 new\(int\) does not escape$" - _ = i -} - -// a backward jump, increases loopdepth -func foo123() { - var i *int - -L1: - i = new(int) // ERROR "new\(int\) escapes to heap$" - - goto L1 - _ = i -} - -func foo124(x **int) { // ERROR "foo124 x does not escape$" - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo124 func literal does not escape$" - *x = p - }() -} - -func foo125(ch chan *int) { // ERROR "foo125 ch does not escape$" - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo125 func literal does not escape$" - ch <- p - }() -} - -func foo126() { - var px *int // loopdepth 0 - for { - // loopdepth 1 - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo126 func literal does not escape$" - px = &i - }() - } - _ = px -} - -var px *int - -func foo127() { - var i int // ERROR "moved to heap: i$" - p := &i - q := p - px = q -} - -func foo128() { - var i int - p := &i - q := p - _ = q -} - -func foo129() { - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo129 func literal does not escape$" - q := p - func() { // ERROR "foo129.func1 func literal does not escape$" - r := q - px = r - }() - }() -} - -func foo130() { - for { - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo130 func literal does not escape$" - px = &i - }() - } -} - -func foo131() { - var i int // ERROR "moved to heap: i$" - func() { // ERROR "foo131 func literal does not escape$" - px = &i - }() -} - -func foo132() { - var i int // ERROR "moved to heap: i$" - go func() { // ERROR "func literal escapes to heap$" - px = &i - }() -} - -func foo133() { - var i int // ERROR "moved to heap: i$" - defer func() { // ERROR "foo133 func literal does not escape$" - px = &i - }() -} - -func foo134() { - var i int - p := &i - func() { // ERROR "foo134 func literal does not escape$" - q := p - func() { // ERROR "foo134.func1 func literal does not escape$" - r := q - _ = r - }() - }() -} - -func foo135() { - var i int // ERROR "moved to heap: i$" - p := &i - go func() { // ERROR "func literal escapes to heap$" - q := p - func() { // ERROR "foo135.func1 func literal does not escape$" - r := q - _ = r - }() - }() -} - -func foo136() { - var i int // ERROR "moved to heap: i$" - p := &i - go func() { // ERROR "func literal escapes to heap$" - q := p - func() { // ERROR "foo136.func1 func literal does not escape$" - r := q - px = r - }() - }() -} - -func foo137() { - var i int // ERROR "moved to heap: i$" - p := &i - func() { // ERROR "foo137 func literal does not escape$" - q := p - go func() { // ERROR "func literal escapes to heap$" - r := q - _ = r - }() - }() -} - -func foo138() *byte { - type T struct { - x [1]byte - } - t := new(T) // ERROR "new\(T\) escapes to heap$" - return &t.x[0] -} - -func foo139() *byte { - type T struct { - x struct { - y byte - } - } - t := new(T) // ERROR "new\(T\) escapes to heap$" - return &t.x.y -} - -// issue 4751 -func foo140() interface{} { - type T struct { - X string - } - type U struct { - X string - T *T - } - t := &T{} // ERROR "&T literal escapes to heap$" - return U{ // ERROR "U literal escapes to heap$" - X: t.X, - T: t, - } -} - -//go:noescape - -func F1([]byte) - -func F2([]byte) - -//go:noescape - -func F3(x []byte) // ERROR "F3 x does not escape$" - -func F4(x []byte) - -func G() { - var buf1 [10]byte - F1(buf1[:]) - - var buf2 [10]byte // ERROR "moved to heap: buf2$" - F2(buf2[:]) - - var buf3 [10]byte - F3(buf3[:]) - - var buf4 [10]byte // ERROR "moved to heap: buf4$" - F4(buf4[:]) -} - -type Tm struct { - x int -} - -func (t *Tm) M() { // ERROR "\(\*Tm\).M t does not escape$" -} - -func foo141() { - var f func() - - 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 "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 "foo143 func literal does not escape$" - for i := 0; i < 1; i++ { - var t Tm - t.M() - } - }() - } -} - -// issue 5773 -// Check that annotations take effect regardless of whether they -// are before or after the use in the source code. - -//go:noescape - -func foo144a(*int) - -func foo144() { - var x int - foo144a(&x) - var y int - foo144b(&y) -} - -//go:noescape - -func foo144b(*int) - -// issue 7313: for loop init should not be treated as "in loop" - -type List struct { - Next *List -} - -func foo145(l List) { // ERROR "foo145 l does not escape$" - var p *List - for p = &l; p.Next != nil; p = p.Next { - } -} - -func foo146(l List) { // ERROR "foo146 l does not escape$" - var p *List - p = &l - for ; p.Next != nil; p = p.Next { - } -} - -func foo147(l List) { // ERROR "foo147 l does not escape$" - var p *List - p = &l - for p.Next != nil { - p = p.Next - } -} - -func foo148(l List) { // ERROR "foo148 l does not escape$" - for p := &l; p.Next != nil; p = p.Next { - } -} - -// related: address of variable should have depth of variable, not of loop - -func foo149(l List) { // ERROR "foo149 l does not escape$" - var p *List - for { - for p = &l; p.Next != nil; p = p.Next { - } - } -} - -// issue 7934: missed ... if element type had no pointers - -var save150 []byte - -func foo150(x ...byte) { // ERROR "leaking param: x$" - save150 = x -} - -func bar150() { - 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$" - save151 = x -} - -func bar151() { - var a [64]int // ERROR "moved to heap: a$" - a[4] = 101 - foo151(&(&a)[4:8][0]) -} - -func bar151b() { - var a [10]int // ERROR "moved to heap: a$" - b := a[:] - foo151(&b[4:8][0]) -} - -func bar151c() { - var a [64]int // ERROR "moved to heap: a$" - a[4] = 101 - foo151(&(&a)[4:8:8][0]) -} - -func bar151d() { - var a [10]int // ERROR "moved to heap: a$" - b := a[:] - foo151(&b[4:8:8][0]) -} - -// issue 8120 - -type U struct { - s *string -} - -func (u *U) String() *string { // ERROR "leaking param: u to result ~r0 level=1$" - return u.s -} - -type V struct { - s *string -} - -// 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$" -} - -func foo152() { - a := "a" // ERROR "moved to heap: a$" - u := U{&a} - 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 to result ~r1 level=-1$" - switch x := v.(type) { - case int: // ERROR "moved to heap: x$" - return &x - } - panic(0) -} - -// issue 8185 - &result escaping into result - -func f() (x int, y *int) { // ERROR "moved to heap: x$" - y = &x - return -} - -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$" - _ = x -} - -func ptrlitNoEscape2() { - // Literal does not escape, but element does. - i := 0 // ERROR "moved to heap: i$" - x := &Lit{&i} // ERROR "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$" - sink = x // ERROR "x escapes to heap$" -} - -// self-assignments - -type Buffer struct { - arr [64]byte - arrPtr *[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 in b.buf1 = b.buf1\[1:2\]$" - b.buf1 = b.buf1[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf1\[1:2:3\]$" - b.buf1 = b.buf2[1:2] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2\]$" - b.buf1 = b.buf2[1:2:3] // ERROR "\(\*Buffer\).foo ignoring self-assignment in b.buf1 = b.buf2\[1:2:3\]$" -} - -func (b *Buffer) bar() { // ERROR "leaking param: b$" - b.buf1 = b.arr[1:2] -} - -func (b *Buffer) arrayPtr() { // ERROR "\(\*Buffer\).arrayPtr b does not escape" - b.buf1 = b.arrPtr[1:2] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2\]$" - b.buf1 = b.arrPtr[1:2:3] // ERROR "\(\*Buffer\).arrayPtr ignoring self-assignment in b.buf1 = b.arrPtr\[1:2:3\]$" -} - -func (b *Buffer) baz() { // ERROR "\(\*Buffer\).baz b does not escape$" - b.str1 = b.str1[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str1\[1:2\]$" - b.str1 = b.str2[1:2] // ERROR "\(\*Buffer\).baz ignoring self-assignment in b.str1 = b.str2\[1:2\]$" -} - -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 in \*sp = \(\*sp\)\[1:2\]$" - *bp = (*bp)[1:2] // ERROR "quux ignoring self-assignment in \*bp = \(\*bp\)\[1:2\]$" -} - -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 - 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] -} - -func issue12397(x, y int) { // ERROR "moved to heap: y$" - // x does not escape below, because all relevant code is dead. - if false { - gxx = &x - } else { - gxx = &y - } - - if true { - gxx = &y - } else { - gxx = &x - } -} diff --git a/test/oldescape5.go b/test/oldescape5.go deleted file mode 100644 index 53d0ff801d..0000000000 --- a/test/oldescape5.go +++ /dev/null @@ -1,247 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// Copyright 2012 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, using compiler diagnostic flags, that the escape analysis is working. -// Compiles but does not run. Inlining is disabled. - -package foo - -import "runtime" - -func noleak(p *int) int { // ERROR "p does not escape" - return *p -} - -func leaktoret(p *int) *int { // ERROR "leaking param: p to result" - return p -} - -func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2" - return p, p -} - -func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3" - return p, q -} - -func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" - return leaktoret22(q, p) -} - -func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2" - r, s := leaktoret22(q, p) - return r, s -} - -func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" - r, s = leaktoret22(q, p) - return -} - -func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" - r, s = leaktoret22(q, p) - return r, s -} - -func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r" - rr, ss := leaktoret22(q, p) - return rr, ss -} - -var gp *int - -func leaktosink(p *int) *int { // ERROR "leaking param: p" - gp = p - return p -} - -func f1() { - var x int - p := noleak(&x) - _ = p -} - -func f2() { - var x int - p := leaktoret(&x) - _ = p -} - -func f3() { - var x int // ERROR "moved to heap: x" - p := leaktoret(&x) - gp = p -} - -func f4() { - var x int // ERROR "moved to heap: x" - p, q := leaktoret2(&x) - gp = p - gp = q -} - -func f5() { - var x int - leaktoret22(leaktoret2(&x)) -} - -func f6() { - var x int // ERROR "moved to heap: x" - px1, px2 := leaktoret22(leaktoret2(&x)) - gp = px1 - _ = px2 -} - -type T struct{ x int } - -func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result" - t.x += u - return t, true -} - -func f7() *T { - r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap" - return r -} - -func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" - return leakrecursive2(q, p) -} - -func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q" - if *p > *q { - return leakrecursive1(q, p) - } - // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges. - return p, q -} - -var global interface{} - -type T1 struct { - X *int -} - -type T2 struct { - Y *T1 -} - -func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p" - if p == nil { - k = T2{} - return - } - - // should make p leak always - global = p // ERROR "p escapes to heap" - return T2{p} -} - -func f9() { - var j T1 // ERROR "moved to heap: j" - f8(&j) -} - -func f10() { - // These don't escape but are too big for the stack - var x [1 << 30]byte // ERROR "moved to heap: x" - var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap" - _ = x[0] + y[0] -} - -// Test for issue 19687 (passing to unnamed parameters does not escape). -func f11(**int) { -} -func f12(_ **int) { -} -func f13() { - var x *int - f11(&x) - f12(&x) - runtime.KeepAlive(&x) // ERROR "&x does not escape" -} - -// Test for issue 24305 (passing to unnamed receivers does not escape). -type U int - -func (*U) M() {} -func (_ *U) N() {} - -func _() { - var u U - u.M() - u.N() -} - -// Issue 24730: taking address in a loop causes unnecessary escape -type T24730 struct { - x [64]byte -} - -func (t *T24730) g() { // ERROR "t does not escape" - y := t.x[:] - for i := range t.x[:] { - y = t.x[:] - y[i] = 1 - } - - var z *byte - for i := range t.x[:] { - z = &t.x[i] - *z = 2 - } -} - -// Issue 15730: copy causes unnecessary escape - -var sink []byte -var sink2 []int -var sink3 []*int - -func f15730a(args ...interface{}) { // ERROR "args does not escape" - for _, arg := range args { - switch a := arg.(type) { - case string: - copy(sink, a) - } - } -} - -func f15730b(args ...interface{}) { // ERROR "args does not escape" - for _, arg := range args { - switch a := arg.(type) { - case []int: - copy(sink2, a) - } - } -} - -func f15730c(args ...interface{}) { // ERROR "leaking param content: args" - for _, arg := range args { - switch a := arg.(type) { - case []*int: - // copy pointerful data should cause escape - copy(sink3, a) - } - } -} - -// Issue 29000: unnamed parameter is not handled correctly - -var sink4 interface{} -var alwaysFalse = false - -func f29000(_ int, x interface{}) { // ERROR "leaking param: x" - sink4 = x - if alwaysFalse { - g29000() - } -} - -func g29000() { - x := 1 - f29000(2, x) // ERROR "x escapes to heap" -} diff --git a/test/oldescape_calls.go b/test/oldescape_calls.go deleted file mode 100644 index 715e832113..0000000000 --- a/test/oldescape_calls.go +++ /dev/null @@ -1,54 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 for function parameters. - -// In this test almost everything is BAD except the simplest cases -// where input directly flows to output. - -package foo - -func f(buf []byte) []byte { // ERROR "leaking param: buf to result ~r1 level=0$" - return buf -} - -func g(*byte) string - -func h(e int) { - var x [32]byte // ERROR "moved to heap: x$" - g(&f(x[:])[0]) -} - -type Node struct { - s string - left, right *Node -} - -func walk(np **Node) int { // ERROR "leaking param content: np" - n := *np - w := len(n.s) - if n == nil { - return 0 - } - wl := walk(&n.left) - wr := walk(&n.right) - if wl < wr { - n.left, n.right = n.right, n.left - wl, wr = wr, wl - } - *np = n - return w + wl + wr -} - -// Test for bug where func var f used prototype's escape analysis results. -func prototype(xyz []string) {} // ERROR "prototype xyz does not escape" -func bar() { - var got [][]string - f := prototype - f = func(ss []string) { got = append(got, ss) } // ERROR "leaking param: ss" "func literal does not escape" - s := "string" - f([]string{s}) // ERROR "\[\]string literal escapes to heap" -} diff --git a/test/oldescape_closure.go b/test/oldescape_closure.go deleted file mode 100644 index 386605dfcd..0000000000 --- a/test/oldescape_closure.go +++ /dev/null @@ -1,173 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 for closure arguments. - -package escape - -var sink interface{} - -func ClosureCallArgs0() { - x := 0 // ERROR "moved to heap: x" - func(p *int) { // ERROR "p does not escape" "func literal does not escape" - *p = 1 - // BAD: x should not escape to heap here - }(&x) -} - -func ClosureCallArgs1() { - x := 0 // ERROR "moved to heap: x" - for { - func(p *int) { // ERROR "p does not escape" "func literal does not escape" - *p = 1 - // BAD: x should not escape to heap here - }(&x) - } -} - -func ClosureCallArgs2() { - for { - // BAD: x should not escape here - x := 0 // ERROR "moved to heap: x" - func(p *int) { // ERROR "p does not escape" "func literal does not escape" - *p = 1 - }(&x) - } -} - -func ClosureCallArgs3() { - x := 0 // ERROR "moved to heap: x" - func(p *int) { // ERROR "leaking param: p" "func literal does not escape" - sink = p // ERROR "p escapes to heap" - }(&x) -} - -func ClosureCallArgs4() { - // BAD: x should not leak here - x := 0 // ERROR "moved to heap: x" - _ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" - return p - }(&x) -} - -func ClosureCallArgs5() { - x := 0 // ERROR "moved to heap: x" - sink = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" "\(func literal\)\(&x\) escapes to heap" - return p - }(&x) -} - -func ClosureCallArgs6() { - x := 0 // ERROR "moved to heap: x" - func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" - sink = &p // ERROR "&p escapes to heap" - }(&x) -} - -func ClosureCallArgs7() { - var pp *int - for { - x := 0 // ERROR "moved to heap: x" - func(p *int) { // ERROR "leaking param: p" "func literal does not escape" - pp = p - }(&x) - } - _ = pp -} - -func ClosureCallArgs8() { - x := 0 // ERROR "moved to heap: x" - defer func(p *int) { // ERROR "p does not escape" "func literal does not escape" - *p = 1 - // BAD: x should not escape to heap here - }(&x) -} - -func ClosureCallArgs9() { - // BAD: x should not leak - x := 0 // ERROR "moved to heap: x" - for { - defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" - *p = 1 - }(&x) - } -} - -func ClosureCallArgs10() { - for { - x := 0 // ERROR "moved to heap: x" - defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" - *p = 1 - }(&x) - } -} - -func ClosureCallArgs11() { - x := 0 // ERROR "moved to heap: x" - defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape" - sink = p // ERROR "p escapes to heap" - }(&x) -} - -func ClosureCallArgs12() { - // BAD: x should not leak - x := 0 // ERROR "moved to heap: x" - defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" - return p - }(&x) -} - -func ClosureCallArgs13() { - x := 0 // ERROR "moved to heap: x" - defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" - sink = &p // ERROR "&p escapes to heap" - }(&x) -} - -func ClosureCallArgs14() { - x := 0 // ERROR "moved to heap: x" - // BAD: &x should not escape here - p := &x // ERROR "moved to heap: p" - _ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" - return *p - // BAD: p should not escape here - }(&p) -} - -func ClosureCallArgs15() { - x := 0 // ERROR "moved to heap: x" - p := &x // ERROR "moved to heap: p" - sink = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape" "\(func literal\)\(&p\) escapes to heap" - return *p - // BAD: p should not escape here - }(&p) -} - -func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape" - t := s + "YYYY" // ERROR "escapes to heap" - return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape" -} - -// See #14409 -- returning part of captured var leaks it. -func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1" - return func() string { // ERROR "ClosureLeak1a func literal does not escape" - return a[0] - }() -} - -func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape" - t := s + "YYYY" // ERROR "escapes to heap" - c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape" - return c -} -func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1" - return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape" - return a[0] - }) -} -func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1" - return f() -} diff --git a/test/oldescape_field.go b/test/oldescape_field.go deleted file mode 100644 index e4213aaf59..0000000000 --- a/test/oldescape_field.go +++ /dev/null @@ -1,174 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 // ERROR "x\.p1 escapes to heap" -} - -func field1() { - i := 0 // ERROR "moved to heap: i$" - var x X - // BAD: &i should not escape - x.p1 = &i - sink = x.p2 // ERROR "x\.p2 escapes to heap" -} - -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] // ERROR "x\.a\[1\] escapes to heap" -} - -// BAD: we are not leaking param x, only x.p2 -func field6(x *X) { // ERROR "leaking param content: x$" - sink = x.p2 // ERROR "x\.p2 escapes to heap" -} - -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 // ERROR "y1\.x\.p1 escapes to heap" -} - -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 // ERROR "y1\.x\.p2 escapes to heap" -} - -func field11() { - i := 0 // ERROR "moved to heap: i$" - x := X{p1: &i} - sink = x.p1 // ERROR "x\.p1 escapes to heap" -} - -func field12() { - i := 0 // ERROR "moved to heap: i$" - // BAD: &i should not escape - x := X{p1: &i} - sink = x.p2 // ERROR "x\.p2 escapes to heap" -} - -func field13() { - i := 0 // ERROR "moved to heap: i$" - x := &X{p1: &i} // ERROR "field13 &X literal does not escape$" - sink = x.p1 // ERROR "x\.p1 escapes to heap" -} - -func field14() { - i := 0 // ERROR "moved to heap: i$" - // BAD: &i should not escape - x := &X{p1: &i} // ERROR "field14 &X literal does not escape$" - sink = x.p2 // ERROR "x\.p2 escapes to heap" -} - -func field15() { - i := 0 // ERROR "moved to heap: i$" - x := &X{p1: &i} // ERROR "&X literal escapes to heap$" - sink = x // ERROR "x escapes to heap" -} - -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 escapes to heap" - x1 := iface.(X) - sink = x1.p2 // ERROR "x1\.p2 escapes to heap" -} - -func field17() { - i := 0 // ERROR "moved to heap: i$" - var x X - x.p1 = &i - var iface interface{} = x // ERROR "x escapes to heap" - x1 := iface.(X) - sink = x1.p1 // ERROR "x1\.p1 escapes to heap" -} - -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 escapes to heap" - y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized. - sink = y // ERROR "y escapes to heap" -} diff --git a/test/oldescape_iface.go b/test/oldescape_iface.go deleted file mode 100644 index 88502df99b..0000000000 --- a/test/oldescape_iface.go +++ /dev/null @@ -1,261 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 for interface conversions. - -package escape - -var sink interface{} - -type M interface { - M() -} - -func mescapes(m M) { // ERROR "leaking param: m" - sink = m // ERROR "m escapes to heap" -} - -func mdoesnotescape(m M) { // ERROR "m does not escape" -} - -// Tests for type stored directly in iface and with value receiver method. -type M0 struct { - p *int -} - -func (M0) M() { -} - -func efaceEscape0() { - { - i := 0 - v := M0{&i} - var x M = v // ERROR "v does not escape" - _ = x - } - { - i := 0 // ERROR "moved to heap: i" - v := M0{&i} - var x M = v // ERROR "v escapes to heap" - sink = x // ERROR "x escapes to heap" - } - { - i := 0 - v := M0{&i} - var x M = v // ERROR "v does not escape" - v1 := x.(M0) - _ = v1 - } - { - i := 0 // ERROR "moved to heap: i" - v := M0{&i} - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - v1 := x.(M0) - sink = v1 // ERROR "v1 escapes to heap" - } - { - i := 0 // ERROR "moved to heap: i" - v := M0{&i} - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - x.M() - } - { - i := 0 // ERROR "moved to heap: i" - v := M0{&i} - var x M = v // ERROR "v escapes to heap" - mescapes(x) - } - { - i := 0 - v := M0{&i} - var x M = v // ERROR "v does not escape" - mdoesnotescape(x) - } -} - -// Tests for type stored indirectly in iface and with value receiver method. -type M1 struct { - p *int - x int -} - -func (M1) M() { -} - -func efaceEscape1() { - { - i := 0 - v := M1{&i, 0} - var x M = v // ERROR "v does not escape" - _ = x - } - { - i := 0 // ERROR "moved to heap: i" - v := M1{&i, 0} - var x M = v // ERROR "v escapes to heap" - sink = x // ERROR "x escapes to heap" - } - { - i := 0 - v := M1{&i, 0} - var x M = v // ERROR "v does not escape" - v1 := x.(M1) - _ = v1 - } - { - i := 0 // ERROR "moved to heap: i" - v := M1{&i, 0} - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - v1 := x.(M1) - sink = v1 // ERROR "v1 escapes to heap" - } - { - i := 0 // ERROR "moved to heap: i" - v := M1{&i, 0} - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - x.M() - } - { - i := 0 // ERROR "moved to heap: i" - v := M1{&i, 0} - var x M = v // ERROR "v escapes to heap" - mescapes(x) - } - { - i := 0 - v := M1{&i, 0} - var x M = v // ERROR "v does not escape" - mdoesnotescape(x) - } -} - -// Tests for type stored directly in iface and with pointer receiver method. -type M2 struct { - p *int -} - -func (*M2) M() { -} - -func efaceEscape2() { - { - i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" - var x M = v // ERROR "v does not escape" - _ = x - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" - var x M = v // ERROR "v escapes to heap" - sink = x // ERROR "x escapes to heap" - } - { - i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" - var x M = v // ERROR "v does not escape" - v1 := x.(*M2) - _ = v1 - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - v1 := x.(*M2) - sink = v1 // ERROR "v1 escapes to heap" - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal does not escape" - // BAD: v does not escape to heap here - var x M = v // ERROR "v does not escape" - v1 := x.(*M2) - sink = *v1 // ERROR "v1 escapes to heap" - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal does not escape" - // BAD: v does not escape to heap here - var x M = v // ERROR "v does not escape" - v1, ok := x.(*M2) - sink = *v1 // ERROR "v1 escapes to heap" - _ = ok - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" - // BAD: v does not escape to heap here - var x M = v // ERROR "v escapes to heap" - x.M() - } - { - i := 0 // ERROR "moved to heap: i" - v := &M2{&i} // ERROR "&M2 literal escapes to heap" - var x M = v // ERROR "v escapes to heap" - mescapes(x) - } - { - i := 0 - v := &M2{&i} // ERROR "&M2 literal does not escape" - var x M = v // ERROR "v does not escape" - mdoesnotescape(x) - } -} - -type T1 struct { - p *int -} - -type T2 struct { - T1 T1 -} - -func dotTypeEscape() *T2 { // #11931 - var x interface{} - x = &T1{p: new(int)} // ERROR "new\(int\) escapes to heap" "&T1 literal does not escape" - return &T2{ - T1: *(x.(*T1)), // ERROR "&T2 literal escapes to heap" - } -} - -func dotTypeEscape2() { // #13805, #15796 - { - i := 0 - j := 0 - var v int - var ok bool - var x interface{} = i // ERROR "i does not escape" - var y interface{} = j // ERROR "j does not escape" - - *(&v) = x.(int) - *(&v), *(&ok) = y.(int) - } - { - i := 0 - j := 0 - var ok bool - var x interface{} = i // ERROR "i does not escape" - var y interface{} = j // ERROR "j does not escape" - - sink = x.(int) // ERROR "x.\(int\) escapes to heap" - sink, *(&ok) = y.(int) - } - { - i := 0 // ERROR "moved to heap: i" - j := 0 // ERROR "moved to heap: j" - var ok bool - var x interface{} = &i // ERROR "&i escapes to heap" - var y interface{} = &j // ERROR "&j escapes to heap" - - sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap" - sink, *(&ok) = y.(*int) - } -} diff --git a/test/oldescape_linkname.go b/test/oldescape_linkname.go deleted file mode 100644 index f99df1bb80..0000000000 --- a/test/oldescape_linkname.go +++ /dev/null @@ -1,15 +0,0 @@ -// errorcheckandrundir -0 -m -l=4 -newescape=false - -// 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. - -// Tests that linknames are included in export data (issue 18167). -package ignored - -/* -Without CL 33911, this test would fail with the following error: - -main.main: relocation target linkname2.byteIndex not defined -main.main: undefined: "linkname2.byteIndex" -*/ diff --git a/test/oldescape_param.go b/test/oldescape_param.go deleted file mode 100644 index 3a3eee2a5b..0000000000 --- a/test/oldescape_param.go +++ /dev/null @@ -1,441 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 for function parameters. - -// In this test almost everything is BAD except the simplest cases -// where input directly flows to output. - -package escape - -func zero() int { return 0 } - -var sink interface{} - -// in -> out -func param0(p *int) *int { // ERROR "leaking param: p to result ~r1" - return p -} - -func caller0a() { - i := 0 - _ = param0(&i) -} - -func caller0b() { - i := 0 // ERROR "moved to heap: i$" - sink = param0(&i) // ERROR "param0\(&i\) escapes to heap" -} - -// in, in -> out, out -func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2" "leaking param: p2 to result ~r3" - return p1, p2 -} - -func caller1() { - i := 0 // ERROR "moved to heap: i$" - j := 0 - sink, _ = param1(&i, &j) -} - -// in -> other in -func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does not escape$" - *p2 = p1 -} - -func caller2a() { - i := 0 // ERROR "moved to heap: i$" - var p *int - param2(&i, &p) - _ = p -} - -func caller2b() { - i := 0 // ERROR "moved to heap: i$" - var p *int - param2(&i, &p) - sink = p // ERROR "p escapes to heap$" -} - -func paramArraySelfAssign(p *PairOfPairs) { // ERROR "p does not escape" - p.pairs[0] = p.pairs[1] // ERROR "ignoring self-assignment in p.pairs\[0\] = p.pairs\[1\]" -} - -func paramArraySelfAssignUnsafeIndex(p *PairOfPairs) { // ERROR "leaking param content: p" - // Function call inside index disables self-assignment case to trigger. - p.pairs[zero()] = p.pairs[1] - p.pairs[zero()+1] = p.pairs[1] -} - -type PairOfPairs struct { - pairs [2]*Pair -} - -type BoxedPair struct { - pair *Pair -} - -type WrappedPair struct { - pair Pair -} - -func leakParam(x interface{}) { // ERROR "leaking param: x" - sink = x -} - -func sinkAfterSelfAssignment1(box *BoxedPair) { // ERROR "leaking param content: box" - box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2" - sink = box.pair.p2 // ERROR "box.pair.p2 escapes to heap" -} - -func sinkAfterSelfAssignment2(box *BoxedPair) { // ERROR "leaking param content: box" - box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2" - sink = box.pair // ERROR "box.pair escapes to heap" -} - -func sinkAfterSelfAssignment3(box *BoxedPair) { // ERROR "leaking param content: box" - box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2" - leakParam(box.pair.p2) // ERROR "box.pair.p2 escapes to heap" -} - -func sinkAfterSelfAssignment4(box *BoxedPair) { // ERROR "leaking param content: box" - box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2" - leakParam(box.pair) // ERROR "box.pair escapes to heap" -} - -func selfAssignmentAndUnrelated(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape" - box1.pair.p1 = box1.pair.p2 // ERROR "ignoring self-assignment in box1.pair.p1 = box1.pair.p2" - leakParam(box2.pair.p2) // ERROR "box2.pair.p2 escapes to heap" -} - -func notSelfAssignment1(box1, box2 *BoxedPair) { // ERROR "leaking param content: box2" "box1 does not escape" - box1.pair.p1 = box2.pair.p1 -} - -func notSelfAssignment2(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape" - p1.pairs[0] = p2.pairs[1] -} - -func notSelfAssignment3(p1, p2 *PairOfPairs) { // ERROR "leaking param content: p2" "p1 does not escape" - p1.pairs[0].p1 = p2.pairs[1].p1 -} - -func boxedPairSelfAssign(box *BoxedPair) { // ERROR "box does not escape" - box.pair.p1 = box.pair.p2 // ERROR "ignoring self-assignment in box.pair.p1 = box.pair.p2" -} - -func wrappedPairSelfAssign(w *WrappedPair) { // ERROR "w does not escape" - w.pair.p1 = w.pair.p2 // ERROR "ignoring self-assignment in w.pair.p1 = w.pair.p2" -} - -// in -> in -type Pair struct { - p1 *int - p2 *int -} - -func param3(p *Pair) { // ERROR "param3 p does not escape" - p.p1 = p.p2 // ERROR "param3 ignoring self-assignment in p.p1 = p.p2" -} - -func caller3a() { - i := 0 - j := 0 - p := Pair{&i, &j} - param3(&p) - _ = p -} - -func caller3b() { - i := 0 // ERROR "moved to heap: i$" - j := 0 // ERROR "moved to heap: j$" - p := Pair{&i, &j} - param3(&p) - sink = p // ERROR "p escapes to heap$" -} - -// in -> rcvr -func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$" "leaking param: i$" - p.p1 = i -} - -func caller4a() { - i := 0 // ERROR "moved to heap: i$" - p := Pair{} - p.param4(&i) - _ = p -} - -func caller4b() { - i := 0 // ERROR "moved to heap: i$" - p := Pair{} - p.param4(&i) - sink = p // ERROR "p escapes to heap$" -} - -// in -> heap -func param5(i *int) { // ERROR "leaking param: i$" - sink = i // ERROR "i escapes to heap$" -} - -func caller5() { - i := 0 // ERROR "moved to heap: i$" - param5(&i) -} - -// *in -> heap -func param6(i ***int) { // ERROR "leaking param content: i$" - sink = *i // ERROR "\*i escapes to heap$" -} - -func caller6a() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - p2 := &p - param6(&p2) -} - -// **in -> heap -func param7(i ***int) { // ERROR "leaking param content: i$" - sink = **i // ERROR "\* \(\*i\) escapes to heap" -} - -func caller7() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - p2 := &p - param7(&p2) -} - -// **in -> heap -func param8(i **int) { // ERROR "param8 i does not escape$" - sink = **i // ERROR "\* \(\*i\) escapes to heap" -} - -func caller8() { - i := 0 - p := &i - param8(&p) -} - -// *in -> out -func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1" - return *p -} - -func caller9a() { - i := 0 - p := &i - p2 := &p - _ = param9(&p2) -} - -func caller9b() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - p2 := &p - sink = param9(&p2) // ERROR "param9\(&p2\) escapes to heap" -} - -// **in -> out -func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2" - return **p -} - -func caller10a() { - i := 0 - p := &i - p2 := &p - _ = param10(&p2) -} - -func caller10b() { - i := 0 // ERROR "moved to heap: i$" - p := &i - p2 := &p - sink = param10(&p2) // ERROR "param10\(&p2\) escapes to heap" -} - -// in escapes to heap (address of param taken and returned) -func param11(i **int) ***int { // ERROR "moved to heap: i$" - return &i -} - -func caller11a() { - i := 0 // ERROR "moved to heap: i" - p := &i // ERROR "moved to heap: p" - _ = param11(&p) -} - -func caller11b() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - sink = param11(&p) // ERROR "param11\(&p\) escapes to heap" -} - -func caller11c() { // GOOD - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p" - sink = *param11(&p) // ERROR "\*param11\(&p\) escapes to heap" -} - -func caller11d() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p" - p2 := &p - sink = param11(p2) // ERROR "param11\(p2\) escapes to heap" -} - -// &in -> rcvr -type Indir struct { - p ***int -} - -func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$" - r.p = &i -} - -func caller12a() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - var r Indir - r.param12(&p) - _ = r -} - -func caller12b() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - r := &Indir{} // ERROR "caller12b &Indir literal does not escape$" - r.param12(&p) - _ = r -} - -func caller12c() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - r := Indir{} - r.param12(&p) - sink = r // ERROR "r escapes to heap$" -} - -func caller12d() { - i := 0 // ERROR "moved to heap: i$" - p := &i // ERROR "moved to heap: p$" - r := Indir{} - r.param12(&p) - sink = **r.p // ERROR "\* \(\*r\.p\) escapes to heap" -} - -// in -> value rcvr -type Val struct { - p **int -} - -func (v Val) param13(i *int) { // ERROR "Val.param13 v does not escape$" "leaking param: i$" - *v.p = i -} - -func caller13a() { - i := 0 // ERROR "moved to heap: i$" - var p *int - var v Val - v.p = &p - v.param13(&i) - _ = v -} - -func caller13b() { - i := 0 // ERROR "moved to heap: i$" - var p *int - v := Val{&p} - v.param13(&i) - _ = v -} - -func caller13c() { - i := 0 // ERROR "moved to heap: i$" - var p *int - v := &Val{&p} // ERROR "caller13c &Val literal does not escape$" - v.param13(&i) - _ = v -} - -func caller13d() { - i := 0 // ERROR "moved to heap: i$" - var p *int // ERROR "moved to heap: p$" - var v Val - v.p = &p - v.param13(&i) - sink = v // ERROR "v escapes to heap$" -} - -func caller13e() { - i := 0 // ERROR "moved to heap: i$" - var p *int // ERROR "moved to heap: p$" - v := Val{&p} - v.param13(&i) - sink = v // ERROR "v escapes to heap$" -} - -func caller13f() { - i := 0 // ERROR "moved to heap: i$" - var p *int // ERROR "moved to heap: p$" - v := &Val{&p} // ERROR "&Val literal escapes to heap$" - v.param13(&i) - sink = v // ERROR "v escapes to heap$" -} - -func caller13g() { - i := 0 // ERROR "moved to heap: i$" - var p *int - v := Val{&p} - v.param13(&i) - sink = *v.p // ERROR "\*v\.p escapes to heap" -} - -func caller13h() { - i := 0 // ERROR "moved to heap: i$" - var p *int - v := &Val{&p} // ERROR "caller13h &Val literal does not escape$" - v.param13(&i) - sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap" -} - -type Node struct { - p *Node -} - -var Sink *Node - -func f(x *Node) { // ERROR "leaking param content: x" - Sink = &Node{x.p} // ERROR "&Node literal escapes to heap" -} - -func g(x *Node) *Node { // ERROR "leaking param: x to result ~r1 level=0" - return &Node{x.p} // ERROR "&Node literal escapes to heap" -} - -func h(x *Node) { // ERROR "leaking param: x" - y := &Node{x} // ERROR "h &Node literal does not escape" - Sink = g(y) - f(y) -} - -// interface(in) -> out -// See also issue 29353. - -// Convert to a non-direct interface, require an allocation and -// copy x to heap (not to result). -func param14a(x [4]*int) interface{} { // ERROR "leaking param: x$" - return x // ERROR "x escapes to heap" -} - -// Convert to a direct interface, does not need an allocation. -// So x only leaks to result. -func param14b(x *int) interface{} { // ERROR "leaking param: x to result ~r1 level=0" - return x // ERROR "x escapes to heap" -} diff --git a/test/oldescape_struct_return.go b/test/oldescape_struct_return.go deleted file mode 100644 index 5088cf863c..0000000000 --- a/test/oldescape_struct_return.go +++ /dev/null @@ -1,74 +0,0 @@ -// errorcheck -0 -m -l -newescape=false - -// 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 for function parameters. - -package foo - -var Ssink *string - -type U struct { - _sp *string - _spp **string -} - -func A(sp *string, spp **string) U { // ERROR "leaking param: sp to result ~r2 level=0$" "leaking param: spp to result ~r2 level=0$" - return U{sp, spp} -} - -func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" "leaking param: spp to result ~r1 level=1$" - return U{*spp, spp} -} - -func tA1() { - s := "cat" - sp := &s - spp := &sp - u := A(sp, spp) - _ = u - println(s) -} - -func tA2() { - s := "cat" - sp := &s - spp := &sp - u := A(sp, spp) - println(*u._sp) -} - -func tA3() { - s := "cat" - sp := &s - spp := &sp - u := A(sp, spp) - println(**u._spp) -} - -func tB1() { - s := "cat" - sp := &s - spp := &sp - u := B(spp) - _ = u - println(s) -} - -func tB2() { - s := "cat" - sp := &s - spp := &sp - u := B(spp) - println(*u._sp) -} - -func tB3() { - s := "cat" - sp := &s - spp := &sp - u := B(spp) - println(**u._spp) -} diff --git a/test/runtime/inlinegcpc.go b/test/runtime/inlinegcpc.go index 0943205ffd..c423993b71 100644 --- a/test/runtime/inlinegcpc.go +++ b/test/runtime/inlinegcpc.go @@ -1,4 +1,4 @@ -// errorcheck -0 -+ -p=runtime -m -newescape=true +// errorcheck -0 -+ -p=runtime -m // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style