Commit 501b786e authored by Matthew Dempsky's avatar Matthew Dempsky

test: remove -newescape from regress tests

Prep for subsequent CLs to remove old escape analysis pass.

This CL removes -newescape=true from tests that use it, and deletes
tests that use -newescape=false. (For history, see CL 170447.)

Notably, this removes escape_because.go without any replacement, but
this is being tracked by #31489.

Change-Id: I6f6058d58fff2c5d210cb1d2713200cc9f501ca7
Reviewed-on: https://go-review.googlesource.com/c/go/+/187617
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 7ed973b4
// 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
......
// 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
......
// 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
......
// 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
*/
// 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
......
// 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
......
// 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
......
// 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
......
// 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
......
// 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
......
// 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
......
// 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
......
// 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
......
// 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)
}
// 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$"
}
// 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
......
This diff is collapsed.
This diff is collapsed.
// 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"
}
// 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"
}
// 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()
}
// 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"
}
This diff is collapsed.
// 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"
*/
This diff is collapsed.
// 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)
}
// 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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment