mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
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: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
7ed973b4d9
commit
501b786e5c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
@ -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$"
|
||||
}
|
@ -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
|
||||
|
1847
test/oldescape2.go
1847
test/oldescape2.go
File diff suppressed because it is too large
Load Diff
1847
test/oldescape2n.go
1847
test/oldescape2n.go
File diff suppressed because it is too large
Load Diff
@ -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"
|
||||
}
|
@ -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"
|
||||
}
|
@ -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()
|
||||
}
|
@ -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"
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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"
|
||||
*/
|
@ -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"
|
||||
}
|
@ -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)
|
||||
}
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user