Commit abefcac1 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: skip escape analysis diagnostics for OADDR

For most nodes (e.g., OPTRLIT, OMAKESLICE, OCONVIFACE), escape
analysis prints "escapes to heap" or "does not escape" to indicate
whether that node's allocation can be heap or stack allocated.

These messages are also emitted for OADDR, even though OADDR does not
actually allocate anything itself. Moreover, it's redundant because
escape analysis already prints "moved to heap" diagnostics when an
OADDR node like "&x" causes x to require heap allocation.

Because OADDR nodes don't allocate memory, my escape analysis rewrite
doesn't naturally emit the "escapes to heap" / "does not escape"
diagnostics for them. It's also non-trivial to replicate the exact
semantics esc.go uses for OADDR.

Since there are so many of these messages, I'm disabling them in this
CL by themselves. I modified esc.go to suppress the Warnl calls
without any other behavior changes, and then used a shell script to
automatically remove any ERROR messages mentioned by run.go in
"missing error" or "no match for" lines.

Fixes #16300.
Updates #23109.

Change-Id: I3993e2743c3ff83ccd0893f4e73b366ff8871a57
Reviewed-on: https://go-review.googlesource.com/c/go/+/170319
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 4ebc6514
...@@ -399,7 +399,7 @@ func escAnalyze(all []*Node, recursive bool) { ...@@ -399,7 +399,7 @@ func escAnalyze(all []*Node, recursive bool) {
if Debug['m'] != 0 { if Debug['m'] != 0 {
for _, n := range e.noesc { for _, n := range e.noesc {
if n.Esc == EscNone { if n.Esc == EscNone && n.Op != OADDR {
Warnl(n.Pos, "%v %S does not escape", e.curfnSym(n), n) Warnl(n.Pos, "%v %S does not escape", e.curfnSym(n), n)
} }
} }
...@@ -1894,7 +1894,7 @@ func (e *EscState) escwalkBody(level Level, dst *Node, src *Node, step *EscStep, ...@@ -1894,7 +1894,7 @@ func (e *EscState) escwalkBody(level Level, dst *Node, src *Node, step *EscStep,
} }
if leaks { if leaks {
src.Esc = EscHeap src.Esc = EscHeap
if Debug['m'] != 0 && osrcesc != src.Esc { if Debug['m'] != 0 && osrcesc != src.Esc && src.Op != OADDR {
p := src p := src
if p.Left.Op == OCLOSURE { if p.Left.Op == OCLOSURE {
p = p.Left // merely to satisfy error messages in tests p = p.Left // merely to satisfy error messages in tests
......
...@@ -208,7 +208,7 @@ func main() { ...@@ -208,7 +208,7 @@ func main() {
func() { // ERROR "func literal does not escape" func() { // ERROR "func literal does not escape"
func() { // ERROR "can inline main.func24" func() { // ERROR "can inline main.func24"
a = 2 a = 2
}() // ERROR "inlining call to main.func24" "&a does not escape" }() // ERROR "inlining call to main.func24"
}() }()
if a != 2 { if a != 2 {
ppanic("a != 2") ppanic("a != 2")
...@@ -220,7 +220,7 @@ func main() { ...@@ -220,7 +220,7 @@ func main() {
func(b int) { // ERROR "func literal does not escape" func(b int) { // ERROR "func literal does not escape"
func() { // ERROR "can inline main.func25.1" func() { // ERROR "can inline main.func25.1"
b = 3 b = 3
}() // ERROR "inlining call to main.func25.1" "&b does not escape" }() // ERROR "inlining call to main.func25.1"
if b != 3 { if b != 3 {
ppanic("b != 3") ppanic("b != 3")
} }
...@@ -272,7 +272,7 @@ func main() { ...@@ -272,7 +272,7 @@ func main() {
a = a * x a = a * x
b = b * y b = b * y
c = c * z c = c * z
}(10) // ERROR "inlining call to main.func28.1.1" "&a does not escape" "&b does not escape" "&c does not escape" }(10) // ERROR "inlining call to main.func28.1.1"
return a + c return a + c
}(100) + b }(100) + b
}(1000); r != 2350 { }(1000); r != 2350 {
......
This diff is collapsed.
This diff is collapsed.
...@@ -12,22 +12,22 @@ package foo ...@@ -12,22 +12,22 @@ package foo
var p *int var p *int
func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x" func alloc(x int) *int { // ERROR "can inline alloc" "moved to heap: x"
return &x // ERROR "&x escapes to heap" return &x
} }
var f func() var f func()
func f1() { func f1() {
p = alloc(2) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x" p = alloc(2) // ERROR "inlining call to alloc" "moved to heap: x"
// Escape analysis used to miss inlined code in closures. // Escape analysis used to miss inlined code in closures.
func() { // ERROR "can inline f1.func1" func() { // ERROR "can inline f1.func1"
p = alloc(3) // ERROR "inlining call to alloc" p = alloc(3) // ERROR "inlining call to alloc"
}() // ERROR "inlining call to f1.func1" "inlining call to alloc" "&x escapes to heap" "moved to heap: x" }() // ERROR "inlining call to f1.func1" "inlining call to alloc" "moved to heap: x"
f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2" f = func() { // ERROR "func literal escapes to heap" "can inline f1.func2"
p = alloc(3) // ERROR "inlining call to alloc" "&x escapes to heap" "moved to heap: x" p = alloc(3) // ERROR "inlining call to alloc" "moved to heap: x"
} }
f() f()
} }
...@@ -43,7 +43,7 @@ func f5() *byte { ...@@ -43,7 +43,7 @@ func f5() *byte {
x [1]byte x [1]byte
} }
t := new(T) // ERROR "new.T. escapes to heap" t := new(T) // ERROR "new.T. escapes to heap"
return &t.x[0] // ERROR "&t.x.0. escapes to heap" return &t.x[0]
} }
func f6() *byte { func f6() *byte {
...@@ -53,5 +53,5 @@ func f6() *byte { ...@@ -53,5 +53,5 @@ func f6() *byte {
} }
} }
t := new(T) // ERROR "new.T. escapes to heap" t := new(T) // ERROR "new.T. escapes to heap"
return &t.x.y // ERROR "&t.x.y escapes to heap" return &t.x.y
} }
...@@ -60,37 +60,37 @@ func leaktosink(p *int) *int { // ERROR "leaking param: p" ...@@ -60,37 +60,37 @@ func leaktosink(p *int) *int { // ERROR "leaking param: p"
func f1() { func f1() {
var x int var x int
p := noleak(&x) // ERROR "&x does not escape" p := noleak(&x)
_ = p _ = p
} }
func f2() { func f2() {
var x int var x int
p := leaktoret(&x) // ERROR "&x does not escape" p := leaktoret(&x)
_ = p _ = p
} }
func f3() { func f3() {
var x int // ERROR "moved to heap: x" var x int // ERROR "moved to heap: x"
p := leaktoret(&x) // ERROR "&x escapes to heap" p := leaktoret(&x)
gp = p gp = p
} }
func f4() { func f4() {
var x int // ERROR "moved to heap: x" var x int // ERROR "moved to heap: x"
p, q := leaktoret2(&x) // ERROR "&x escapes to heap" p, q := leaktoret2(&x)
gp = p gp = p
gp = q gp = q
} }
func f5() { func f5() {
var x int var x int
leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape" leaktoret22(leaktoret2(&x))
} }
func f6() { func f6() {
var x int // ERROR "moved to heap: x" var x int // ERROR "moved to heap: x"
px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap" px1, px2 := leaktoret22(leaktoret2(&x))
gp = px1 gp = px1
_ = px2 _ = px2
} }
...@@ -142,7 +142,7 @@ func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: ...@@ -142,7 +142,7 @@ func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param:
func f9() { func f9() {
var j T1 // ERROR "moved to heap: j" var j T1 // ERROR "moved to heap: j"
f8(&j) // ERROR "&j escapes to heap" f8(&j)
} }
func f10() { func f10() {
...@@ -159,8 +159,8 @@ func f12(_ **int) { ...@@ -159,8 +159,8 @@ func f12(_ **int) {
} }
func f13() { func f13() {
var x *int var x *int
f11(&x) // ERROR "&x does not escape" f11(&x)
f12(&x) // ERROR "&x does not escape" f12(&x)
runtime.KeepAlive(&x) // ERROR "&x does not escape" runtime.KeepAlive(&x) // ERROR "&x does not escape"
} }
...@@ -172,8 +172,8 @@ func (_ *U) N() {} ...@@ -172,8 +172,8 @@ func (_ *U) N() {}
func _() { func _() {
var u U var u U
u.M() // ERROR "u does not escape" u.M()
u.N() // ERROR "u does not escape" u.N()
} }
// Issue 24730: taking address in a loop causes unnecessary escape // Issue 24730: taking address in a loop causes unnecessary escape
...@@ -182,15 +182,15 @@ type T24730 struct { ...@@ -182,15 +182,15 @@ type T24730 struct {
} }
func (t *T24730) g() { // ERROR "t does not escape" func (t *T24730) g() { // ERROR "t does not escape"
y := t.x[:] // ERROR "t\.x does not escape" y := t.x[:]
for i := range t.x[:] { // ERROR "t\.x does not escape" for i := range t.x[:] {
y = t.x[:] // ERROR "t\.x does not escape" y = t.x[:]
y[i] = 1 y[i] = 1
} }
var z *byte var z *byte
for i := range t.x[:] { // ERROR "t\.x does not escape" for i := range t.x[:] {
z = &t.x[i] // ERROR "t\.x\[i\] does not escape" z = &t.x[i]
*z = 2 *z = 2
} }
} }
......
...@@ -27,16 +27,16 @@ func bff(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "l ...@@ -27,16 +27,16 @@ func bff(a, b *string) U { // ERROR "leaking param: a to result ~r2 level=0$" "l
func tbff1() *string { func tbff1() *string {
a := "cat" a := "cat"
b := "dog" // ERROR "moved to heap: b$" b := "dog" // ERROR "moved to heap: b$"
u := bff(&a, &b) // ERROR "tbff1 &a does not escape$" "tbff1 &b does not escape$" u := bff(&a, &b)
_ = u[0] _ = u[0]
return &b // ERROR "&b escapes to heap$" return &b
} }
// BAD: need fine-grained analysis to track u[0] and u[1] differently. // BAD: need fine-grained analysis to track u[0] and u[1] differently.
func tbff2() *string { func tbff2() *string {
a := "cat" // ERROR "moved to heap: a$" a := "cat" // ERROR "moved to heap: a$"
b := "dog" // ERROR "moved to heap: b$" b := "dog" // ERROR "moved to heap: b$"
u := bff(&a, &b) // ERROR "&a escapes to heap$" "&b escapes to heap$" u := bff(&a, &b)
_ = u[0] _ = u[0]
return u[1] return u[1]
} }
......
...@@ -40,7 +40,7 @@ func f2(q *int) { // ERROR "from &u \(address-of\) at escape_because.go:43$" "fr ...@@ -40,7 +40,7 @@ func f2(q *int) { // ERROR "from &u \(address-of\) at escape_because.go:43$" "fr
s := q s := q
t := pair{s, nil} t := pair{s, nil}
u := t // ERROR "moved to heap: u$" u := t // ERROR "moved to heap: u$"
sink = &u // ERROR "&u escapes to heap$" "from &u \(interface-converted\) at escape_because.go:43$" "from sink \(assigned to top level variable\) at escape_because.go:43$" 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" 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"
...@@ -78,7 +78,7 @@ func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go ...@@ -78,7 +78,7 @@ func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go
return y return y
} }
x-- x--
return f8(*y, &x) // ERROR "&x escapes to heap$" "from y \(arg to recursive call\) at escape_because.go:81$" "from ~r2 \(return\) at escape_because.go:78$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$" 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$" 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$"
...@@ -86,7 +86,7 @@ func f9(x int, y ...*int) *int { // ERROR "from y\[0\] \(dot of pointer\) at esc ...@@ -86,7 +86,7 @@ func f9(x int, y ...*int) *int { // ERROR "from y\[0\] \(dot of pointer\) at esc
return y[0] return y[0]
} }
x-- x--
return f9(*y[0], &x) // ERROR "&x escapes to heap$" "f9 ... argument does not escape$" "from ... argument \(... arg to recursive call\) at escape_because.go:89$" 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$" 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$"
...@@ -132,14 +132,14 @@ func leakThroughOAS2() { ...@@ -132,14 +132,14 @@ func leakThroughOAS2() {
// See #26987. // See #26987.
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
j := 0 // ERROR "moved to heap: j$" 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$" "from &i \(interface-converted\) at escape_because.go:135$" "&j escapes to heap$" "from &j \(interface-converted\) at escape_because.go:135" sink, sink = &i, &j // ERROR "&i escapes to heap$" "from sink \(assign-pair\) at escape_because.go:135$" "&j escapes to heap$"
} }
func leakThroughOAS2FUNC() { func leakThroughOAS2FUNC() {
// See #26987. // See #26987.
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
j := 0 j := 0
sink, _ = leakParams(&i, &j) // ERROR "&i escapes to heap$" "&j does not escape$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:142$" "from sink \(assign-pair-func-call\) at escape_because.go:142$" sink, _ = leakParams(&i, &j)
} }
// The list below is all of the why-escapes messages seen building the escape analysis tests. // The list below is all of the why-escapes messages seen building the escape analysis tests.
......
...@@ -19,7 +19,7 @@ func g(*byte) string ...@@ -19,7 +19,7 @@ func g(*byte) string
func h(e int) { func h(e int) {
var x [32]byte // ERROR "moved to heap: x$" var x [32]byte // ERROR "moved to heap: x$"
g(&f(x[:])[0]) // ERROR "&f\(x\[:\]\)\[0\] escapes to heap$" "x escapes to heap$" g(&f(x[:])[0])
} }
type Node struct { type Node struct {
...@@ -33,8 +33,8 @@ func walk(np **Node) int { // ERROR "leaking param content: np" ...@@ -33,8 +33,8 @@ func walk(np **Node) int { // ERROR "leaking param content: np"
if n == nil { if n == nil {
return 0 return 0
} }
wl := walk(&n.left) // ERROR "walk &n.left does not escape" wl := walk(&n.left)
wr := walk(&n.right) // ERROR "walk &n.right does not escape" wr := walk(&n.right)
if wl < wr { if wl < wr {
n.left, n.right = n.right, n.left n.left, n.right = n.right, n.left
wl, wr = wr, wl wl, wr = wr, wl
......
...@@ -15,7 +15,7 @@ func ClosureCallArgs0() { ...@@ -15,7 +15,7 @@ func ClosureCallArgs0() {
func(p *int) { // ERROR "p does not escape" "func literal does not escape" func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1 *p = 1
// BAD: x should not escape to heap here // BAD: x should not escape to heap here
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs1() { func ClosureCallArgs1() {
...@@ -24,7 +24,7 @@ func ClosureCallArgs1() { ...@@ -24,7 +24,7 @@ func ClosureCallArgs1() {
func(p *int) { // ERROR "p does not escape" "func literal does not escape" func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1 *p = 1
// BAD: x should not escape to heap here // BAD: x should not escape to heap here
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
} }
...@@ -34,7 +34,7 @@ func ClosureCallArgs2() { ...@@ -34,7 +34,7 @@ func ClosureCallArgs2() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "p does not escape" "func literal does not escape" func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1 *p = 1
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
} }
...@@ -42,7 +42,7 @@ func ClosureCallArgs3() { ...@@ -42,7 +42,7 @@ func ClosureCallArgs3() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "leaking param: p" "func literal does not escape" func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
sink = p // ERROR "p escapes to heap" sink = p // ERROR "p escapes to heap"
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs4() { func ClosureCallArgs4() {
...@@ -50,21 +50,21 @@ func ClosureCallArgs4() { ...@@ -50,21 +50,21 @@ func ClosureCallArgs4() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
_ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" _ = func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
return p return p
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs5() { func ClosureCallArgs5() {
x := 0 // ERROR "moved to heap: x" 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" 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 return p
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs6() { func ClosureCallArgs6() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
sink = &p // ERROR "&p escapes to heap" sink = &p // ERROR "&p escapes to heap"
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs7() { func ClosureCallArgs7() {
...@@ -73,7 +73,7 @@ func ClosureCallArgs7() { ...@@ -73,7 +73,7 @@ func ClosureCallArgs7() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
func(p *int) { // ERROR "leaking param: p" "func literal does not escape" func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
pp = p pp = p
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
_ = pp _ = pp
} }
...@@ -83,7 +83,7 @@ func ClosureCallArgs8() { ...@@ -83,7 +83,7 @@ func ClosureCallArgs8() {
defer func(p *int) { // ERROR "p does not escape" "func literal does not escape" defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
*p = 1 *p = 1
// BAD: x should not escape to heap here // BAD: x should not escape to heap here
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs9() { func ClosureCallArgs9() {
...@@ -92,7 +92,7 @@ func ClosureCallArgs9() { ...@@ -92,7 +92,7 @@ func ClosureCallArgs9() {
for { for {
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
*p = 1 *p = 1
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
} }
...@@ -101,7 +101,7 @@ func ClosureCallArgs10() { ...@@ -101,7 +101,7 @@ func ClosureCallArgs10() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape"
*p = 1 *p = 1
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
} }
...@@ -109,7 +109,7 @@ func ClosureCallArgs11() { ...@@ -109,7 +109,7 @@ func ClosureCallArgs11() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape" defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape"
sink = p // ERROR "p escapes to heap" sink = p // ERROR "p escapes to heap"
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs12() { func ClosureCallArgs12() {
...@@ -117,33 +117,33 @@ func ClosureCallArgs12() { ...@@ -117,33 +117,33 @@ func ClosureCallArgs12() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape" defer func(p *int) *int { // ERROR "leaking param: p to result ~r1" "func literal does not escape"
return p return p
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs13() { func ClosureCallArgs13() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape"
sink = &p // ERROR "&p escapes to heap" sink = &p // ERROR "&p escapes to heap"
}(&x) // ERROR "&x escapes to heap" }(&x)
} }
func ClosureCallArgs14() { func ClosureCallArgs14() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
// BAD: &x should not escape here // BAD: &x should not escape here
p := &x // ERROR "moved to heap: p" "&x escapes to heap" 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" _ = func(p **int) *int { // ERROR "leaking param: p to result ~r1 level=1" "func literal does not escape"
return *p return *p
// BAD: p should not escape here // BAD: p should not escape here
}(&p) // ERROR "&p escapes to heap" }(&p)
} }
func ClosureCallArgs15() { func ClosureCallArgs15() {
x := 0 // ERROR "moved to heap: x" x := 0 // ERROR "moved to heap: x"
p := &x // ERROR "moved to heap: p" "&x escapes to heap" 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" 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 return *p
// BAD: p should not escape here // BAD: p should not escape here
}(&p) // ERROR "&p escapes to heap" }(&p)
} }
func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape" func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
......
...@@ -23,7 +23,7 @@ type Y struct { ...@@ -23,7 +23,7 @@ type Y struct {
func field0() { func field0() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
sink = x.p1 // ERROR "x\.p1 escapes to heap" sink = x.p1 // ERROR "x\.p1 escapes to heap"
} }
...@@ -31,21 +31,21 @@ func field1() { ...@@ -31,21 +31,21 @@ func field1() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
// BAD: &i should not escape // BAD: &i should not escape
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
sink = x.p2 // ERROR "x\.p2 escapes to heap" sink = x.p2 // ERROR "x\.p2 escapes to heap"
} }
func field3() { func field3() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
func field4() { func field4() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var y Y var y Y
y.x.p1 = &i // ERROR "&i escapes to heap$" y.x.p1 = &i
x := y.x x := y.x
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
...@@ -54,7 +54,7 @@ func field5() { ...@@ -54,7 +54,7 @@ func field5() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
// BAD: &i should not escape here // BAD: &i should not escape here
x.a[0] = &i // ERROR "&i escapes to heap$" x.a[0] = &i
sink = x.a[1] // ERROR "x\.a\[1\] escapes to heap" sink = x.a[1] // ERROR "x\.a\[1\] escapes to heap"
} }
...@@ -67,14 +67,14 @@ func field6a() { ...@@ -67,14 +67,14 @@ func field6a() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
// BAD: &i should not escape // BAD: &i should not escape
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
field6(&x) // ERROR "field6a &x does not escape" field6(&x)
} }
func field7() { func field7() {
i := 0 i := 0
var y Y var y Y
y.x.p1 = &i // ERROR "field7 &i does not escape$" y.x.p1 = &i
x := y.x x := y.x
var y1 Y var y1 Y
y1.x = x y1.x = x
...@@ -84,7 +84,7 @@ func field7() { ...@@ -84,7 +84,7 @@ func field7() {
func field8() { func field8() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var y Y var y Y
y.x.p1 = &i // ERROR "&i escapes to heap$" y.x.p1 = &i
x := y.x x := y.x
var y1 Y var y1 Y
y1.x = x y1.x = x
...@@ -94,7 +94,7 @@ func field8() { ...@@ -94,7 +94,7 @@ func field8() {
func field9() { func field9() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var y Y var y Y
y.x.p1 = &i // ERROR "&i escapes to heap$" y.x.p1 = &i
x := y.x x := y.x
var y1 Y var y1 Y
y1.x = x y1.x = x
...@@ -105,7 +105,7 @@ func field10() { ...@@ -105,7 +105,7 @@ func field10() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var y Y var y Y
// BAD: &i should not escape // BAD: &i should not escape
y.x.p1 = &i // ERROR "&i escapes to heap$" y.x.p1 = &i
x := y.x x := y.x
var y1 Y var y1 Y
y1.x = x y1.x = x
...@@ -114,33 +114,33 @@ func field10() { ...@@ -114,33 +114,33 @@ func field10() {
func field11() { func field11() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
x := X{p1: &i} // ERROR "&i escapes to heap$" x := X{p1: &i}
sink = x.p1 // ERROR "x\.p1 escapes to heap" sink = x.p1 // ERROR "x\.p1 escapes to heap"
} }
func field12() { func field12() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
// BAD: &i should not escape // BAD: &i should not escape
x := X{p1: &i} // ERROR "&i escapes to heap$" x := X{p1: &i}
sink = x.p2 // ERROR "x\.p2 escapes to heap" sink = x.p2 // ERROR "x\.p2 escapes to heap"
} }
func field13() { func field13() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
x := &X{p1: &i} // ERROR "&i escapes to heap$" "field13 &X literal does not escape$" x := &X{p1: &i} // ERROR "field13 &X literal does not escape$"
sink = x.p1 // ERROR "x\.p1 escapes to heap" sink = x.p1 // ERROR "x\.p1 escapes to heap"
} }
func field14() { func field14() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
// BAD: &i should not escape // BAD: &i should not escape
x := &X{p1: &i} // ERROR "&i escapes to heap$" "field14 &X literal does not escape$" x := &X{p1: &i} // ERROR "field14 &X literal does not escape$"
sink = x.p2 // ERROR "x\.p2 escapes to heap" sink = x.p2 // ERROR "x\.p2 escapes to heap"
} }
func field15() { func field15() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
x := &X{p1: &i} // ERROR "&X literal escapes to heap$" "&i escapes to heap$" x := &X{p1: &i} // ERROR "&X literal escapes to heap$"
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
...@@ -148,7 +148,7 @@ func field16() { ...@@ -148,7 +148,7 @@ func field16() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
// BAD: &i should not escape // BAD: &i should not escape
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
var iface interface{} = x // ERROR "x escapes to heap" var iface interface{} = x // ERROR "x escapes to heap"
x1 := iface.(X) x1 := iface.(X)
sink = x1.p2 // ERROR "x1\.p2 escapes to heap" sink = x1.p2 // ERROR "x1\.p2 escapes to heap"
...@@ -157,7 +157,7 @@ func field16() { ...@@ -157,7 +157,7 @@ func field16() {
func field17() { func field17() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
var iface interface{} = x // ERROR "x escapes to heap" var iface interface{} = x // ERROR "x escapes to heap"
x1 := iface.(X) x1 := iface.(X)
sink = x1.p1 // ERROR "x1\.p1 escapes to heap" sink = x1.p1 // ERROR "x1\.p1 escapes to heap"
...@@ -167,7 +167,7 @@ func field18() { ...@@ -167,7 +167,7 @@ func field18() {
i := 0 // ERROR "moved to heap: i$" i := 0 // ERROR "moved to heap: i$"
var x X var x X
// BAD: &i should not escape // BAD: &i should not escape
x.p1 = &i // ERROR "&i escapes to heap$" x.p1 = &i
var iface interface{} = x // ERROR "x escapes to heap" 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. y, _ := iface.(Y) // Put X, but extracted Y. The cast will fail, so y is zero initialized.
sink = y // ERROR "y escapes to heap" sink = y // ERROR "y escapes to heap"
......
...@@ -32,26 +32,26 @@ func (M0) M() { ...@@ -32,26 +32,26 @@ func (M0) M() {
func efaceEscape0() { func efaceEscape0() {
{ {
i := 0 i := 0
v := M0{&i} // ERROR "&i does not escape" v := M0{&i}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
_ = x _ = x
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M0{&i} // ERROR "&i escapes to heap" v := M0{&i}
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
{ {
i := 0 i := 0
v := M0{&i} // ERROR "&i does not escape" v := M0{&i}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
v1 := x.(M0) v1 := x.(M0)
_ = v1 _ = v1
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M0{&i} // ERROR "&i escapes to heap" v := M0{&i}
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
v1 := x.(M0) v1 := x.(M0)
...@@ -59,20 +59,20 @@ func efaceEscape0() { ...@@ -59,20 +59,20 @@ func efaceEscape0() {
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M0{&i} // ERROR "&i escapes to heap" v := M0{&i}
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
x.M() x.M()
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M0{&i} // ERROR "&i escapes to heap" v := M0{&i}
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
mescapes(x) mescapes(x)
} }
{ {
i := 0 i := 0
v := M0{&i} // ERROR "&i does not escape" v := M0{&i}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
mdoesnotescape(x) mdoesnotescape(x)
} }
...@@ -90,26 +90,26 @@ func (M1) M() { ...@@ -90,26 +90,26 @@ func (M1) M() {
func efaceEscape1() { func efaceEscape1() {
{ {
i := 0 i := 0
v := M1{&i, 0} // ERROR "&i does not escape" v := M1{&i, 0}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
_ = x _ = x
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M1{&i, 0} // ERROR "&i escapes to heap" v := M1{&i, 0}
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
{ {
i := 0 i := 0
v := M1{&i, 0} // ERROR "&i does not escape" v := M1{&i, 0}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
v1 := x.(M1) v1 := x.(M1)
_ = v1 _ = v1
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M1{&i, 0} // ERROR "&i escapes to heap" v := M1{&i, 0}
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
v1 := x.(M1) v1 := x.(M1)
...@@ -117,20 +117,20 @@ func efaceEscape1() { ...@@ -117,20 +117,20 @@ func efaceEscape1() {
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M1{&i, 0} // ERROR "&i escapes to heap" v := M1{&i, 0}
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
x.M() x.M()
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := M1{&i, 0} // ERROR "&i escapes to heap" v := M1{&i, 0}
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
mescapes(x) mescapes(x)
} }
{ {
i := 0 i := 0
v := M1{&i, 0} // ERROR "&i does not escape" v := M1{&i, 0}
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
mdoesnotescape(x) mdoesnotescape(x)
} }
...@@ -147,26 +147,26 @@ func (*M2) M() { ...@@ -147,26 +147,26 @@ func (*M2) M() {
func efaceEscape2() { func efaceEscape2() {
{ {
i := 0 i := 0
v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape" v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
_ = x _ = x
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap" v := &M2{&i} // ERROR "&M2 literal escapes to heap"
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
{ {
i := 0 i := 0
v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape" v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
v1 := x.(*M2) v1 := x.(*M2)
_ = v1 _ = v1
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap" v := &M2{&i} // ERROR "&M2 literal escapes to heap"
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
v1 := x.(*M2) v1 := x.(*M2)
...@@ -174,7 +174,7 @@ func efaceEscape2() { ...@@ -174,7 +174,7 @@ func efaceEscape2() {
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape" v := &M2{&i} // ERROR "&M2 literal does not escape"
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
v1 := x.(*M2) v1 := x.(*M2)
...@@ -182,7 +182,7 @@ func efaceEscape2() { ...@@ -182,7 +182,7 @@ func efaceEscape2() {
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal does not escape" v := &M2{&i} // ERROR "&M2 literal does not escape"
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
v1, ok := x.(*M2) v1, ok := x.(*M2)
...@@ -191,20 +191,20 @@ func efaceEscape2() { ...@@ -191,20 +191,20 @@ func efaceEscape2() {
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap" v := &M2{&i} // ERROR "&M2 literal escapes to heap"
// BAD: v does not escape to heap here // BAD: v does not escape to heap here
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
x.M() x.M()
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
v := &M2{&i} // ERROR "&i escapes to heap" "&M2 literal escapes to heap" v := &M2{&i} // ERROR "&M2 literal escapes to heap"
var x M = v // ERROR "v escapes to heap" var x M = v // ERROR "v escapes to heap"
mescapes(x) mescapes(x)
} }
{ {
i := 0 i := 0
v := &M2{&i} // ERROR "&i does not escape" "&M2 literal does not escape" v := &M2{&i} // ERROR "&M2 literal does not escape"
var x M = v // ERROR "v does not escape" var x M = v // ERROR "v does not escape"
mdoesnotescape(x) mdoesnotescape(x)
} }
...@@ -235,8 +235,8 @@ func dotTypeEscape2() { // #13805, #15796 ...@@ -235,8 +235,8 @@ func dotTypeEscape2() { // #13805, #15796
var x interface{} = i // ERROR "i does not escape" var x interface{} = i // ERROR "i does not escape"
var y interface{} = j // ERROR "j does not escape" var y interface{} = j // ERROR "j does not escape"
*(&v) = x.(int) // ERROR "&v does not escape" *(&v) = x.(int)
*(&v), *(&ok) = y.(int) // ERROR "&v does not escape" "&ok does not escape" *(&v), *(&ok) = y.(int)
} }
{ {
i := 0 i := 0
...@@ -246,7 +246,7 @@ func dotTypeEscape2() { // #13805, #15796 ...@@ -246,7 +246,7 @@ func dotTypeEscape2() { // #13805, #15796
var y interface{} = j // ERROR "j does not escape" var y interface{} = j // ERROR "j does not escape"
sink = x.(int) // ERROR "x.\(int\) escapes to heap" sink = x.(int) // ERROR "x.\(int\) escapes to heap"
sink, *(&ok) = y.(int) // ERROR "&ok does not escape" sink, *(&ok) = y.(int)
} }
{ {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
...@@ -256,6 +256,6 @@ func dotTypeEscape2() { // #13805, #15796 ...@@ -256,6 +256,6 @@ func dotTypeEscape2() { // #13805, #15796
var y interface{} = &j // ERROR "&j escapes to heap" var y interface{} = &j // ERROR "&j escapes to heap"
sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap" sink = x.(*int) // ERROR "x.\(\*int\) escapes to heap"
sink, *(&ok) = y.(*int) // ERROR "&ok does not escape" sink, *(&ok) = y.(*int)
} }
} }
...@@ -25,42 +25,42 @@ func constptr0() { ...@@ -25,42 +25,42 @@ func constptr0() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
// BAD: i should not escape here // BAD: i should not escape here
x.p = &i // ERROR "&i escapes to heap" x.p = &i
_ = x _ = x
} }
func constptr01() *ConstPtr { func constptr01() *ConstPtr {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap"
x.p = &i // ERROR "&i escapes to heap" x.p = &i
return x return x
} }
func constptr02() ConstPtr { func constptr02() ConstPtr {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
x.p = &i // ERROR "&i escapes to heap" x.p = &i
return *x return *x
} }
func constptr03() **ConstPtr { func constptr03() **ConstPtr {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" "moved to heap: x" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" "moved to heap: x"
x.p = &i // ERROR "&i escapes to heap" x.p = &i
return &x // ERROR "&x escapes to heap" return &x
} }
func constptr1() { func constptr1() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap" x := &ConstPtr{} // ERROR "&ConstPtr literal escapes to heap"
x.p = &i // ERROR "&i escapes to heap" x.p = &i
sink = x // ERROR "x escapes to heap" sink = x // ERROR "x escapes to heap"
} }
func constptr2() { func constptr2() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" x := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
x.p = &i // ERROR "&i escapes to heap" x.p = &i
sink = *x // ERROR "\*x escapes to heap" sink = *x // ERROR "\*x escapes to heap"
} }
...@@ -87,15 +87,15 @@ func constptr6(p *ConstPtr) { // ERROR "leaking param content: p" ...@@ -87,15 +87,15 @@ func constptr6(p *ConstPtr) { // ERROR "leaking param content: p"
func constptr7() **ConstPtr { func constptr7() **ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" "moved to heap: p" p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" "moved to heap: p"
var tmp ConstPtr2 var tmp ConstPtr2
p1 := &tmp // ERROR "&tmp does not escape" p1 := &tmp
p.c = *p1 p.c = *p1
return &p // ERROR "&p escapes to heap" return &p
} }
func constptr8() *ConstPtr { func constptr8() *ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap"
var tmp ConstPtr2 var tmp ConstPtr2
p.c = *&tmp // ERROR "&tmp does not escape" p.c = *&tmp
return p return p
} }
...@@ -103,7 +103,7 @@ func constptr9() ConstPtr { ...@@ -103,7 +103,7 @@ func constptr9() ConstPtr {
p := new(ConstPtr) // ERROR "new\(ConstPtr\) does not escape" p := new(ConstPtr) // ERROR "new\(ConstPtr\) does not escape"
var p1 ConstPtr2 var p1 ConstPtr2
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p1.p = &i // ERROR "&i escapes to heap" p1.p = &i
p.c = p1 p.c = p1
return *p return *p
} }
...@@ -112,9 +112,9 @@ func constptr10() ConstPtr { ...@@ -112,9 +112,9 @@ func constptr10() ConstPtr {
x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr literal escapes to heap" x := &ConstPtr{} // ERROR "moved to heap: x" "&ConstPtr literal escapes to heap"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
var p *ConstPtr var p *ConstPtr
p = &ConstPtr{p: &i, x: &x} // ERROR "&i escapes to heap" "&x escapes to heap" "&ConstPtr literal does not escape" p = &ConstPtr{p: &i, x: &x} // ERROR "&ConstPtr literal does not escape"
var pp **ConstPtr var pp **ConstPtr
pp = &p // ERROR "&p does not escape" pp = &p
return **pp return **pp
} }
...@@ -122,7 +122,7 @@ func constptr11() *ConstPtr { ...@@ -122,7 +122,7 @@ func constptr11() *ConstPtr {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap" p := new(ConstPtr) // ERROR "new\(ConstPtr\) escapes to heap"
p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape" p1 := &ConstPtr{} // ERROR "&ConstPtr literal does not escape"
p1.p = &i // ERROR "&i escapes to heap" p1.p = &i
*p = *p1 *p = *p1
return p return p
} }
...@@ -130,13 +130,13 @@ func constptr11() *ConstPtr { ...@@ -130,13 +130,13 @@ func constptr11() *ConstPtr {
func foo(p **int) { // ERROR "foo p does not escape" func foo(p **int) { // ERROR "foo p does not escape"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
y := p y := p
*y = &i // ERROR "&i escapes to heap" *y = &i
} }
func foo1(p *int) { // ERROR "p does not escape" func foo1(p *int) { // ERROR "p does not escape"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
y := &p // ERROR "&p does not escape" y := &p
*y = &i // ERROR "&i escapes to heap" *y = &i
} }
func foo2() { func foo2() {
...@@ -146,15 +146,15 @@ func foo2() { ...@@ -146,15 +146,15 @@ func foo2() {
x := new(int) // ERROR "moved to heap: x" "new\(int\) escapes to heap" x := new(int) // ERROR "moved to heap: x" "new\(int\) escapes to heap"
sink = &x // ERROR "&x escapes to heap" sink = &x // ERROR "&x escapes to heap"
var z Z var z Z
z.f = &x // ERROR "&x does not escape" z.f = &x
p := z.f p := z.f
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
*p = &i // ERROR "&i escapes to heap" *p = &i
} }
var global *byte var global *byte
func f() { func f() {
var x byte // ERROR "moved to heap: x" var x byte // ERROR "moved to heap: x"
global = &*&x // ERROR "&\(\*\(&x\)\) escapes to heap" "&x escapes to heap" global = &*&x
} }
...@@ -12,64 +12,64 @@ var sink interface{} ...@@ -12,64 +12,64 @@ var sink interface{}
func level0() { func level0() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap" p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "moved to heap: p1" "&p0 escapes to heap" p1 := &p0 // ERROR "moved to heap: p1"
p2 := &p1 // ERROR "moved to heap: p2" "&p1 escapes to heap" p2 := &p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap" sink = &p2 // ERROR "&p2 escapes to heap"
} }
func level1() { func level1() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap" p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "moved to heap: p1" "&p0 escapes to heap" p1 := &p0 // ERROR "moved to heap: p1"
p2 := &p1 // ERROR "&p1 escapes to heap" p2 := &p1
sink = p2 // ERROR "p2 escapes to heap" sink = p2 // ERROR "p2 escapes to heap"
} }
func level2() { func level2() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap" p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "&p0 escapes to heap" p1 := &p0
p2 := &p1 // ERROR "&p1 does not escape" p2 := &p1
sink = *p2 // ERROR "\*p2 escapes to heap" sink = *p2 // ERROR "\*p2 escapes to heap"
} }
func level3() { func level3() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "&i escapes to heap" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
p2 := &p1 // ERROR "&p1 does not escape" p2 := &p1
sink = **p2 // ERROR "\* \(\*p2\) escapes to heap" sink = **p2 // ERROR "\* \(\*p2\) escapes to heap"
} }
func level4() { func level4() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap" p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "&p0 escapes to heap" p1 := &p0
p2 := p1 // ERROR "moved to heap: p2" p2 := p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap" sink = &p2 // ERROR "&p2 escapes to heap"
} }
func level5() { func level5() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "moved to heap: p0" "&i escapes to heap" p0 := &i // ERROR "moved to heap: p0"
p1 := &p0 // ERROR "&p0 escapes to heap" p1 := &p0
p2 := p1 p2 := p1
sink = p2 // ERROR "p2 escapes to heap" sink = p2 // ERROR "p2 escapes to heap"
} }
func level6() { func level6() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "&i escapes to heap" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
p2 := p1 p2 := p1
sink = *p2 // ERROR "\*p2 escapes to heap" sink = *p2 // ERROR "\*p2 escapes to heap"
} }
func level7() { func level7() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "&i escapes to heap" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
// note *p1 == &i // note *p1 == &i
p2 := *p1 // ERROR "moved to heap: p2" p2 := *p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap" sink = &p2 // ERROR "&p2 escapes to heap"
...@@ -77,32 +77,32 @@ func level7() { ...@@ -77,32 +77,32 @@ func level7() {
func level8() { func level8() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
p0 := &i // ERROR "&i escapes to heap" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
p2 := *p1 p2 := *p1
sink = p2 // ERROR "p2 escapes to heap" sink = p2 // ERROR "p2 escapes to heap"
} }
func level9() { func level9() {
i := 0 i := 0
p0 := &i // ERROR "&i does not escape" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
p2 := *p1 p2 := *p1
sink = *p2 // ERROR "\*p2 escapes to heap" sink = *p2 // ERROR "\*p2 escapes to heap"
} }
func level10() { func level10() {
i := 0 i := 0
p0 := &i // ERROR "&i does not escape" p0 := &i
p1 := *p0 p1 := *p0
p2 := &p1 // ERROR "&p1 does not escape" p2 := &p1
sink = *p2 // ERROR "\*p2 escapes to heap" sink = *p2 // ERROR "\*p2 escapes to heap"
} }
func level11() { func level11() {
i := 0 i := 0
p0 := &i // ERROR "&i does not escape" p0 := &i
p1 := &p0 // ERROR "&p0 does not escape" p1 := &p0
p2 := **p1 // ERROR "moved to heap: p2" p2 := **p1 // ERROR "moved to heap: p2"
sink = &p2 // ERROR "&p2 escapes to heap" sink = &p2 // ERROR "&p2 escapes to heap"
} }
...@@ -16,7 +16,7 @@ func map0() { ...@@ -16,7 +16,7 @@ func map0() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape // BAD: j should not escape
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
_ = m _ = m
} }
...@@ -25,15 +25,15 @@ func map1() *int { ...@@ -25,15 +25,15 @@ func map1() *int {
// BAD: i should not escape // BAD: i should not escape
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
return m[&i] // ERROR "&i does not escape" return m[&i]
} }
func map2() map[*int]*int { func map2() map[*int]*int {
m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) escapes to heap" m := make(map[*int]*int) // ERROR "make\(map\[\*int\]\*int\) escapes to heap"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
return m return m
} }
...@@ -42,7 +42,7 @@ func map3() []*int { ...@@ -42,7 +42,7 @@ func map3() []*int {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape // BAD: j should not escape
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
var r []*int var r []*int
for k := range m { for k := range m {
r = append(r, k) r = append(r, k)
...@@ -55,7 +55,7 @@ func map4() []*int { ...@@ -55,7 +55,7 @@ func map4() []*int {
// BAD: i should not escape // BAD: i should not escape
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
var r []*int var r []*int
for k, v := range m { for k, v := range m {
// We want to test exactly "for k, v := range m" rather than "for _, v := range m". // We want to test exactly "for k, v := range m" rather than "for _, v := range m".
...@@ -70,7 +70,7 @@ func map4() []*int { ...@@ -70,7 +70,7 @@ func map4() []*int {
func map5(m map[*int]*int) { // ERROR "m does not escape" func map5(m map[*int]*int) { // ERROR "m does not escape"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
} }
func map6(m map[*int]*int) { // ERROR "m does not escape" func map6(m map[*int]*int) { // ERROR "m does not escape"
...@@ -79,7 +79,7 @@ func map6(m map[*int]*int) { // ERROR "m does not escape" ...@@ -79,7 +79,7 @@ func map6(m map[*int]*int) { // ERROR "m does not escape"
} }
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m[&i] = &j // ERROR "&i escapes to heap" "&j escapes to heap" m[&i] = &j
} }
func map7() { func map7() {
...@@ -87,14 +87,14 @@ func map7() { ...@@ -87,14 +87,14 @@ func map7() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
// BAD: j should not escape // BAD: j should not escape
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal does not escape" m := map[*int]*int{&i: &j} // ERROR "literal does not escape"
_ = m _ = m
} }
func map8() { func map8() {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal escapes to heap" m := map[*int]*int{&i: &j} // ERROR "literal escapes to heap"
sink = m // ERROR "m escapes to heap" sink = m // ERROR "m escapes to heap"
} }
...@@ -102,6 +102,6 @@ func map9() *int { ...@@ -102,6 +102,6 @@ func map9() *int {
// BAD: i should not escape // BAD: i should not escape
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
j := 0 // ERROR "moved to heap: j" j := 0 // ERROR "moved to heap: j"
m := map[*int]*int{&i: &j} // ERROR "&i escapes to heap" "&j escapes to heap" "literal does not escape" m := map[*int]*int{&i: &j} // ERROR "literal does not escape"
return m[nil] return m[nil]
} }
This diff is collapsed.
...@@ -19,28 +19,28 @@ func slice0() { ...@@ -19,28 +19,28 @@ func slice0() {
var s []*int var s []*int
// BAD: i should not escape // BAD: i should not escape
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s = append(s, &i) // ERROR "&i escapes to heap" s = append(s, &i)
_ = s _ = s
} }
func slice1() *int { func slice1() *int {
var s []*int var s []*int
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s = append(s, &i) // ERROR "&i escapes to heap" s = append(s, &i)
return s[0] return s[0]
} }
func slice2() []*int { func slice2() []*int {
var s []*int var s []*int
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s = append(s, &i) // ERROR "&i escapes to heap" s = append(s, &i)
return s return s
} }
func slice3() *int { func slice3() *int {
var s []*int var s []*int
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s = append(s, &i) // ERROR "&i escapes to heap" s = append(s, &i)
for _, p := range s { for _, p := range s {
return p return p
} }
...@@ -49,7 +49,7 @@ func slice3() *int { ...@@ -49,7 +49,7 @@ func slice3() *int {
func slice4(s []*int) { // ERROR "s does not escape" func slice4(s []*int) { // ERROR "s does not escape"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s[0] = &i // ERROR "&i escapes to heap" s[0] = &i
} }
func slice5(s []*int) { // ERROR "s does not escape" func slice5(s []*int) { // ERROR "s does not escape"
...@@ -57,39 +57,39 @@ func slice5(s []*int) { // ERROR "s does not escape" ...@@ -57,39 +57,39 @@ func slice5(s []*int) { // ERROR "s does not escape"
s = make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape" s = make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
} }
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s[0] = &i // ERROR "&i escapes to heap" s[0] = &i
} }
func slice6() { func slice6() {
s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape" s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
// BAD: i should not escape // BAD: i should not escape
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s[0] = &i // ERROR "&i escapes to heap" s[0] = &i
_ = s _ = s
} }
func slice7() *int { func slice7() *int {
s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape" s := make([]*int, 10) // ERROR "make\(\[\]\*int, 10\) does not escape"
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s[0] = &i // ERROR "&i escapes to heap" s[0] = &i
return s[0] return s[0]
} }
func slice8() { func slice8() {
i := 0 i := 0
s := []*int{&i} // ERROR "&i does not escape" "literal does not escape" s := []*int{&i} // ERROR "literal does not escape"
_ = s _ = s
} }
func slice9() *int { func slice9() *int {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s := []*int{&i} // ERROR "&i escapes to heap" "literal does not escape" s := []*int{&i} // ERROR "literal does not escape"
return s[0] return s[0]
} }
func slice10() []*int { func slice10() []*int {
i := 0 // ERROR "moved to heap: i" i := 0 // ERROR "moved to heap: i"
s := []*int{&i} // ERROR "&i escapes to heap" "literal escapes to heap" s := []*int{&i} // ERROR "literal escapes to heap"
return s return s
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,8 +25,8 @@ func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" "l ...@@ -25,8 +25,8 @@ func B(spp **string) U { // ERROR "leaking param: spp to result ~r1 level=0$" "l
func tA1() { func tA1() {
s := "cat" s := "cat"
sp := &s // ERROR "tA1 &s does not escape$" sp := &s
spp := &sp // ERROR "tA1 &sp does not escape$" spp := &sp
u := A(sp, spp) u := A(sp, spp)
_ = u _ = u
println(s) println(s)
...@@ -34,24 +34,24 @@ func tA1() { ...@@ -34,24 +34,24 @@ func tA1() {
func tA2() { func tA2() {
s := "cat" s := "cat"
sp := &s // ERROR "tA2 &s does not escape$" sp := &s
spp := &sp // ERROR "tA2 &sp does not escape$" spp := &sp
u := A(sp, spp) u := A(sp, spp)
println(*u._sp) println(*u._sp)
} }
func tA3() { func tA3() {
s := "cat" s := "cat"
sp := &s // ERROR "tA3 &s does not escape$" sp := &s
spp := &sp // ERROR "tA3 &sp does not escape$" spp := &sp
u := A(sp, spp) u := A(sp, spp)
println(**u._spp) println(**u._spp)
} }
func tB1() { func tB1() {
s := "cat" s := "cat"
sp := &s // ERROR "tB1 &s does not escape$" sp := &s
spp := &sp // ERROR "tB1 &sp does not escape$" spp := &sp
u := B(spp) u := B(spp)
_ = u _ = u
println(s) println(s)
...@@ -59,16 +59,16 @@ func tB1() { ...@@ -59,16 +59,16 @@ func tB1() {
func tB2() { func tB2() {
s := "cat" s := "cat"
sp := &s // ERROR "tB2 &s does not escape$" sp := &s
spp := &sp // ERROR "tB2 &sp does not escape$" spp := &sp
u := B(spp) u := B(spp)
println(*u._sp) println(*u._sp)
} }
func tB3() { func tB3() {
s := "cat" s := "cat"
sp := &s // ERROR "tB3 &s does not escape$" sp := &s
spp := &sp // ERROR "tB3 &sp does not escape$" spp := &sp
u := B(spp) u := B(spp)
println(**u._spp) println(**u._spp)
} }
...@@ -37,28 +37,28 @@ func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals" ...@@ -37,28 +37,28 @@ func FooNz(vals ...*int) (s int) { // ERROR "leaking param: vals"
func TFooN() { func TFooN() {
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
var i, j int var i, j int
FooN(&i, &j) // ERROR "TFooN &i does not escape" "TFooN &j does not escape" "TFooN ... argument does not escape" FooN(&i, &j) // ERROR "TFooN ... argument does not escape"
} }
} }
func TFooNx() { func TFooNx() {
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k" var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
FooNx(&k, &i, &j) // ERROR "&k escapes to heap" "&i escapes to heap" "&j escapes to heap" "TFooNx ... argument does not escape" FooNx(&k, &i, &j) // ERROR "TFooNx ... argument does not escape"
} }
} }
func TFooNy() { func TFooNy() {
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k" var i, j, k int // ERROR "moved to heap: i" "moved to heap: j" "moved to heap: k"
FooNy(&k, &i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "&k escapes to heap" "... argument escapes to heap" FooNy(&k, &i, &j) // ERROR "... argument escapes to heap"
} }
} }
func TFooNz() { func TFooNz() {
for i := 0; i < 1000; i++ { for i := 0; i < 1000; i++ {
var i, j int // ERROR "moved to heap: i" "moved to heap: j" var i, j int // ERROR "moved to heap: i" "moved to heap: j"
FooNz(&i, &j) // ERROR "&i escapes to heap" "&j escapes to heap" "... argument escapes to heap" FooNz(&i, &j) // ERROR "... argument escapes to heap"
} }
} }
...@@ -83,7 +83,7 @@ func FooI(args ...interface{}) { // ERROR "leaking param content: args" ...@@ -83,7 +83,7 @@ func FooI(args ...interface{}) { // ERROR "leaking param content: args"
func TFooI() { func TFooI() {
a := int32(1) // ERROR "moved to heap: a" a := int32(1) // ERROR "moved to heap: a"
b := "cat" b := "cat"
c := &a // ERROR "&a escapes to heap" c := &a
FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape" FooI(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooI ... argument does not escape"
} }
...@@ -107,14 +107,14 @@ func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result ...@@ -107,14 +107,14 @@ func FooJ(args ...interface{}) *int32 { // ERROR "leaking param: args to result
func TFooJ1() { func TFooJ1() {
a := int32(1) a := int32(1)
b := "cat" b := "cat"
c := &a // ERROR "TFooJ1 &a does not escape" 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" 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() { func TFooJ2() {
a := int32(1) // ERROR "moved to heap: a" a := int32(1) // ERROR "moved to heap: a"
b := "cat" b := "cat"
c := &a // ERROR "&a escapes to heap" 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" isink = FooJ(a, b, c) // ERROR "a escapes to heap" "b escapes to heap" "c escapes to heap" "TFooJ2 ... argument does not escape"
} }
...@@ -143,7 +143,7 @@ func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 l ...@@ -143,7 +143,7 @@ func FooK(args fakeSlice) *int32 { // ERROR "leaking param: args to result ~r1 l
func TFooK2() { func TFooK2() {
a := int32(1) // ERROR "moved to heap: a" a := int32(1) // ERROR "moved to heap: a"
b := "cat" b := "cat"
c := &a // ERROR "&a escapes to heap" 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" 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) isink = FooK(fs)
} }
...@@ -168,7 +168,7 @@ func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~ ...@@ -168,7 +168,7 @@ func FooL(args []interface{}) *int32 { // ERROR "leaking param: args to result ~
func TFooL2() { func TFooL2() {
a := int32(1) // ERROR "moved to heap: a" a := int32(1) // ERROR "moved to heap: a"
b := "cat" b := "cat"
c := &a // ERROR "&a escapes to heap" 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" 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) isink = FooL(s)
} }
...@@ -18,7 +18,7 @@ type B struct { ...@@ -18,7 +18,7 @@ type B struct {
} }
func f(a A) int { func f(a A) int {
for i, x := range &a.b { // ERROR "f &a.b does not escape" for i, x := range &a.b {
if x != 0 { if x != 0 {
return 64*i + int(x) return 64*i + int(x)
} }
...@@ -27,7 +27,7 @@ func f(a A) int { ...@@ -27,7 +27,7 @@ func f(a A) int {
} }
func g(a *A) int { // ERROR "g a does not escape" func g(a *A) int { // ERROR "g a does not escape"
for i, x := range &a.b { // ERROR "g &a.b does not escape" for i, x := range &a.b {
if x != 0 { if x != 0 {
return 64*i + int(x) return 64*i + int(x)
} }
...@@ -36,7 +36,7 @@ func g(a *A) int { // ERROR "g a does not escape" ...@@ -36,7 +36,7 @@ func g(a *A) int { // ERROR "g a does not escape"
} }
func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
for i, x := range &a.b { // ERROR "h &a.b does not escape" for i, x := range &a.b {
if i == 0 { if i == 0 {
return x return x
} }
...@@ -45,7 +45,7 @@ func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" ...@@ -45,7 +45,7 @@ func h(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
} }
func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
p := &a.b // ERROR "h2 &a.b does not escape" p := &a.b
for i, x := range p { for i, x := range p {
if i == 0 { if i == 0 {
return x return x
...@@ -56,7 +56,7 @@ func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1" ...@@ -56,7 +56,7 @@ func h2(a *B) *uint64 { // ERROR "leaking param: a to result ~r1 level=1"
// Seems like below should be level=1, not 0. // Seems like below should be level=1, not 0.
func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0" func k(a B) *uint64 { // ERROR "leaking param: a to result ~r1 level=0"
for i, x := range &a.b { // ERROR "k &a.b does not escape" for i, x := range &a.b {
if i == 0 { if i == 0 {
return x return x
} }
...@@ -70,16 +70,16 @@ func main() { ...@@ -70,16 +70,16 @@ func main() {
var a1, a2 A var a1, a2 A
var b1, b2, b3, b4 B var b1, b2, b3, b4 B
var x1, x2, x3, x4 uint64 // ERROR "moved to heap: x1" "moved to heap: x3" var x1, x2, x3, x4 uint64 // ERROR "moved to heap: x1" "moved to heap: x3"
b1.b[0] = &x1 // ERROR "&x1 escapes to heap" b1.b[0] = &x1
b2.b[0] = &x2 // ERROR "main &x2 does not escape" b2.b[0] = &x2
b3.b[0] = &x3 // ERROR "&x3 escapes to heap" b3.b[0] = &x3
b4.b[0] = &x4 // ERROR "main &x4 does not escape" b4.b[0] = &x4
f(a1) f(a1)
g(&a2) // ERROR "main &a2 does not escape" g(&a2)
sink = h(&b1) // ERROR "main &b1 does not escape" sink = h(&b1)
h(&b2) // ERROR "main &b2 does not escape" h(&b2)
sink = h2(&b1) // ERROR "main &b1 does not escape" sink = h2(&b1)
h2(&b4) // ERROR "main &b4 does not escape" h2(&b4)
x1 = 17 x1 = 17
println("*sink=", *sink) // Verify that sink addresses x1 println("*sink=", *sink) // Verify that sink addresses x1
x3 = 42 x3 = 42
......
...@@ -50,10 +50,10 @@ func test1(iter int) { ...@@ -50,10 +50,10 @@ func test1(iter int) {
// var fn func() // this makes it work, because fn stays off heap // var fn func() // this makes it work, because fn stays off heap
j := 0 // ERROR "moved to heap: j$" j := 0 // ERROR "moved to heap: j$"
fn = func() { // ERROR "func literal escapes to heap$" fn = func() { // ERROR "func literal escapes to heap$"
m[i] = append(m[i], 0) // ERROR "&i escapes to heap$" m[i] = append(m[i], 0)
if j < 25 { // ERROR "&j escapes to heap$" if j < 25 {
j++ j++
fn() // ERROR "&fn escapes to heap$" fn()
} }
} }
fn() fn()
...@@ -92,16 +92,16 @@ func test3(iter int) { ...@@ -92,16 +92,16 @@ func test3(iter int) {
const maxI = 500 const maxI = 500
var x int // ERROR "moved to heap: x$" var x int // ERROR "moved to heap: x$"
m := &x // ERROR "&x escapes to heap$" m := &x
var fn func() // ERROR "moved to heap: fn$" var fn func() // ERROR "moved to heap: fn$"
for i := 0; i < maxI; i++ { for i := 0; i < maxI; i++ {
// var fn func() // this makes it work, because fn stays off heap // var fn func() // this makes it work, because fn stays off heap
j := 0 // ERROR "moved to heap: j$" j := 0 // ERROR "moved to heap: j$"
fn = func() { // ERROR "func literal escapes to heap$" fn = func() { // ERROR "func literal escapes to heap$"
if j < 100 { // ERROR "&j escapes to heap$" if j < 100 {
j++ j++
fn() // ERROR "&fn escapes to heap$" fn()
} else { } else {
*m = *m + 1 *m = *m + 1
} }
...@@ -118,7 +118,7 @@ func test4(iter int) { ...@@ -118,7 +118,7 @@ func test4(iter int) {
const maxI = 500 const maxI = 500
var x int var x int
m := &x // ERROR "test4 &x does not escape$" m := &x
// var fn func() // var fn func()
for i := 0; i < maxI; i++ { for i := 0; i < maxI; i++ {
...@@ -157,7 +157,7 @@ func test5(iter int) { ...@@ -157,7 +157,7 @@ func test5(iter int) {
const maxI = 500 const maxI = 500
var x int // ERROR "moved to heap: x$" var x int // ERROR "moved to heap: x$"
m := &x // ERROR "&x escapes to heap$" m := &x
var fn *str var fn *str
for i := 0; i < maxI; i++ { for i := 0; i < maxI; i++ {
...@@ -175,7 +175,7 @@ func test6(iter int) { ...@@ -175,7 +175,7 @@ func test6(iter int) {
const maxI = 500 const maxI = 500
var x int var x int
m := &x // ERROR "&x does not escape$" m := &x
// var fn *str // var fn *str
for i := 0; i < maxI; i++ { for i := 0; i < maxI; i++ {
......
...@@ -22,8 +22,8 @@ func toString(b immutableBytes) string { // ERROR "leaking param: b$" ...@@ -22,8 +22,8 @@ func toString(b immutableBytes) string { // ERROR "leaking param: b$"
return s return s
} }
strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s)) // ERROR "toString &s does not escape$" strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))
strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data // ERROR "toString &b does not escape$" strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data
l := len(b) l := len(b)
strHeader.Len = l strHeader.Len = l
......
...@@ -17,7 +17,7 @@ func F1() { ...@@ -17,7 +17,7 @@ func F1() {
var s S // ERROR "moved to heap: s" var s S // ERROR "moved to heap: s"
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
fs := []func(){ // ERROR "F1 \[\]func\(\) literal does not escape" fs := []func(){ // ERROR "F1 \[\]func\(\) literal does not escape"
s.Inc, // ERROR "F1 s.Inc does not escape" "s escapes to heap" s.Inc, // ERROR "F1 s.Inc does not escape"
} }
for _, f := range fs { for _, f := range fs {
f() f()
...@@ -29,7 +29,7 @@ func F2() { ...@@ -29,7 +29,7 @@ func F2() {
var s S // ERROR "moved to heap: s" var s S // ERROR "moved to heap: s"
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
for _, f := range []func(){ // ERROR "F2 \[\]func\(\) literal does not escape" for _, f := range []func(){ // ERROR "F2 \[\]func\(\) literal does not escape"
s.Inc, // ERROR "F2 s.Inc does not escape" "s escapes to heap" s.Inc, // ERROR "F2 s.Inc does not escape"
} { } {
f() f()
} }
......
...@@ -19,8 +19,8 @@ func F2([]byte) ...@@ -19,8 +19,8 @@ func F2([]byte)
func G() { func G() {
var buf1 [10]byte var buf1 [10]byte
F1(buf1[:]) // ERROR "buf1 does not escape" F1(buf1[:])
var buf2 [10]byte // ERROR "moved to heap: buf2" var buf2 [10]byte // ERROR "moved to heap: buf2"
F2(buf2[:]) // ERROR "buf2 escapes to heap" F2(buf2[:])
} }
...@@ -17,9 +17,9 @@ func bufferNotEscape() string { ...@@ -17,9 +17,9 @@ func bufferNotEscape() string {
// copied during String() call, but object "handle" itself // copied during String() call, but object "handle" itself
// can be stack-allocated. // can be stack-allocated.
var b bytes.Buffer var b bytes.Buffer
b.WriteString("123") // ERROR "bufferNotEscape b does not escape$" b.WriteString("123")
b.Write([]byte{'4'}) // ERROR "bufferNotEscape \[\]byte literal does not escape$" "bufferNotEscape b does not escape$" b.Write([]byte{'4'}) // ERROR "bufferNotEscape \[\]byte literal does not escape$"
return b.String() // ERROR "bufferNotEscape b does not escape$" "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$" return b.String() // ERROR "inlining call to bytes.\(\*Buffer\).String$" "string\(bytes.b.buf\[bytes.b.off:\]\) escapes to heap$"
} }
func bufferNoEscape2(xs []string) int { // ERROR "bufferNoEscape2 xs does not escape$" func bufferNoEscape2(xs []string) int { // ERROR "bufferNoEscape2 xs does not escape$"
...@@ -41,9 +41,9 @@ func bufferNoEscape3(xs []string) string { // ERROR "bufferNoEscape3 xs does not ...@@ -41,9 +41,9 @@ func bufferNoEscape3(xs []string) string { // ERROR "bufferNoEscape3 xs does not
func bufferNoEscape4() []byte { func bufferNoEscape4() []byte {
var b bytes.Buffer var b bytes.Buffer
b.Grow(64) // ERROR "bufferNoEscape4 b does not escape$" "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$" b.Grow(64) // ERROR "bufferNoEscape4 ignoring self-assignment in bytes.b.buf = bytes.b.buf\[:bytes.m·3\]$" "inlining call to bytes.\(\*Buffer\).Grow$"
useBuffer(&b) // ERROR "bufferNoEscape4 &b does not escape$" useBuffer(&b)
return b.Bytes() // ERROR "bufferNoEscape4 b does not escape$" "inlining call to bytes.\(\*Buffer\).Bytes$" return b.Bytes() // ERROR "inlining call to bytes.\(\*Buffer\).Bytes$"
} }
func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$" func bufferNoEscape5() { // ERROR "can inline bufferNoEscape5$"
......
...@@ -74,7 +74,7 @@ func m() int { ...@@ -74,7 +74,7 @@ func m() int {
// address taking prevents closure inlining // address taking prevents closure inlining
func n() int { func n() int {
foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape" foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
bar := &foo // ERROR "&foo does not escape" bar := &foo
x := (*bar)() + foo() x := (*bar)() + foo()
return x return x
} }
...@@ -115,7 +115,7 @@ func s0(x int) int { ...@@ -115,7 +115,7 @@ func s0(x int) int {
foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape" foo := func() { // ERROR "can inline s0.func1" "s0 func literal does not escape"
x = x + 1 x = x + 1
} }
foo() // ERROR "inlining call to s0.func1" "&x does not escape" foo() // ERROR "inlining call to s0.func1"
return x return x
} }
...@@ -124,7 +124,7 @@ func s1(x int) int { ...@@ -124,7 +124,7 @@ func s1(x int) int {
return x return x
} }
x = x + 1 x = x + 1
return foo() // ERROR "inlining call to s1.func1" "&x does not escape" return foo() // ERROR "inlining call to s1.func1"
} }
// can't currently inline functions with a break statement // can't currently inline functions with a break statement
......
...@@ -24,30 +24,30 @@ var mutex *sync.Mutex ...@@ -24,30 +24,30 @@ var mutex *sync.Mutex
func small5() { // ERROR "can inline small5" func small5() { // ERROR "can inline small5"
// the Unlock fast path should be inlined // the Unlock fast path should be inlined
mutex.Unlock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Unlock" "&sync\.m\.state escapes to heap" mutex.Unlock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Unlock"
} }
func small6() { // ERROR "can inline small6" func small6() { // ERROR "can inline small6"
// the Lock fast path should be inlined // the Lock fast path should be inlined
mutex.Lock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Lock" "&sync\.m\.state escapes to heap" mutex.Lock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Lock"
} }
var once *sync.Once var once *sync.Once
func small7() { // ERROR "can inline small7" func small7() { // ERROR "can inline small7"
// the Do fast path should be inlined // the Do fast path should be inlined
once.Do(small5) // ERROR "inlining call to sync\.\(\*Once\)\.Do" "&sync\.o\.done escapes to heap" once.Do(small5) // ERROR "inlining call to sync\.\(\*Once\)\.Do"
} }
var rwmutex *sync.RWMutex var rwmutex *sync.RWMutex
func small8() { // ERROR "can inline small8" func small8() { // ERROR "can inline small8"
// the RUnlock fast path should be inlined // the RUnlock fast path should be inlined
rwmutex.RUnlock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RUnlock" "&sync\.rw\.readerCount escapes to heap" rwmutex.RUnlock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RUnlock"
} }
func small9() { // ERROR "can inline small9" func small9() { // ERROR "can inline small9"
// the RLock fast path should be inlined // the RLock fast path should be inlined
rwmutex.RLock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RLock" "&sync\.rw\.readerCount escapes to heap" "&sync\.rw\.readerSem escapes to heap" rwmutex.RLock() // ERROR "inlining call to sync\.\(\*RWMutex\)\.RLock"
} }
...@@ -19,22 +19,22 @@ func f(uintptr) // ERROR "f assuming arg#1 is unsafe uintptr" ...@@ -19,22 +19,22 @@ func f(uintptr) // ERROR "f assuming arg#1 is unsafe uintptr"
func g() { // ERROR "can inline g" func g() { // ERROR "can inline g"
var t int var t int
f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "g &t does not escape" "stack object .autotmp_[0-9]+ unsafe.Pointer$" f(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
} }
func h() { // ERROR "can inline h" func h() { // ERROR "can inline h"
var v int var v int
syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "h &v does not escape" "stack object .autotmp_[0-9]+ unsafe.Pointer$" syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
} }
func i() { // ERROR "can inline i" func i() { // ERROR "can inline i"
var t int var t int
p := unsafe.Pointer(&t) // ERROR "i &t does not escape" p := unsafe.Pointer(&t)
f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" f(uintptr(p)) // ERROR "live at call to f: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
} }
func j() { // ERROR "can inline j" func j() { // ERROR "can inline j"
var v int var v int
p := unsafe.Pointer(&v) // ERROR "j &v does not escape" p := unsafe.Pointer(&v)
syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$" syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
} }
...@@ -30,9 +30,9 @@ func F4(...uintptr) {} // ERROR "escaping ...uintptr" ...@@ -30,9 +30,9 @@ func F4(...uintptr) {} // ERROR "escaping ...uintptr"
func G() { func G() {
var t int // ERROR "moved to heap" var t int // ERROR "moved to heap"
F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "&t escapes to heap" "stack object .autotmp_[0-9]+ unsafe.Pointer$" F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
var t2 int // ERROR "moved to heap" var t2 int // ERROR "moved to heap"
F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp" "&t2 escapes to heap" F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp"
} }
func H() { func H() {
......
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