]> Cypherpunks.ru repositories - gostls13.git/blobdiff - test/escape5.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / escape5.go
index 6a138ea0903fd7162f250b6c8d3f508da012835c..133d973ba5d5f8290d7f2746f6a2c28918350a79 100644 (file)
@@ -1,6 +1,6 @@
 // errorcheck -0 -m -l
 
-// Copyright 2012 The Go Authors.  All rights reserved.
+// 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.
 
@@ -9,6 +9,11 @@
 
 package foo
 
+import (
+       "runtime"
+       "unsafe"
+)
+
 func noleak(p *int) int { // ERROR "p does not escape"
        return *p
 }
@@ -17,19 +22,19 @@ 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"
+func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: p to result ~r1"
        return p, p
 }
 
-func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
+func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: q to result ~r1"
        return p, q
 }
 
-func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
+func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0"
        return leaktoret22(q, p)
 }
 
-func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
+func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0"
        r, s := leaktoret22(q, p)
        return r, s
 }
@@ -58,37 +63,37 @@ func leaktosink(p *int) *int { // ERROR "leaking param: p"
 
 func f1() {
        var x int
-       p := noleak(&x) // ERROR "&x does not escape"
+       p := noleak(&x)
        _ = p
 }
 
 func f2() {
        var x int
-       p := leaktoret(&x) // ERROR "&x does not escape"
+       p := leaktoret(&x)
        _ = p
 }
 
 func f3() {
-       var x int          // ERROR "moved to heap: x"
-       p := leaktoret(&x) // ERROR "&x escapes to heap"
+       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) // ERROR "&x escapes to heap"
+       var x int // ERROR "moved to heap: x"
+       p, q := leaktoret2(&x)
        gp = p
        gp = q
 }
 
 func f5() {
        var x int
-       leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
+       leaktoret22(leaktoret2(&x))
 }
 
 func f6() {
-       var x int                               // ERROR "moved to heap: x"
-       px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
+       var x int // ERROR "moved to heap: x"
+       px1, px2 := leaktoret22(leaktoret2(&x))
        gp = px1
        _ = px2
 }
@@ -127,25 +132,150 @@ type T2 struct {
        Y *T1
 }
 
-func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
+func f8(p *T1) (k T2) { // ERROR "leaking param: p$"
        if p == nil {
                k = T2{}
                return
        }
 
        // should make p leak always
-       global = p // ERROR "p escapes to heap"
+       global = p
        return T2{p}
 }
 
 func f9() {
        var j T1 // ERROR "moved to heap: j"
-       f8(&j)   // ERROR "&j escapes to heap"
+       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"
+       var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1073741824\) 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)
+}
+
+// Test for issue 24305 (passing to unnamed receivers does not escape).
+type U int
+
+func (*U) M()   {}
+func (_ *U) N() {}
+
+func fbad24305a() {
+       var u U
+       u.M()
+       u.N()
+}
+
+func fbad24305b() {
+       var u U
+       (*U).M(&u)
+       (*U).N(&u)
+}
+
+// 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"
+}
+
+// Issue 28369: taking an address of a parameter and converting it into a uintptr causes an
+// unnecessary escape.
+
+var sink28369 uintptr
+
+func f28369(n int) int {
+       if n == 0 {
+               sink28369 = uintptr(unsafe.Pointer(&n))
+               return n
+       }
+
+       return 1 + f28369(n-1)
+}
+
+// Issue 44614: parameters that flow to a heap-allocated result
+// parameter must be recorded as a heap-flow rather than a
+// result-flow.
+
+// N.B., must match "leaking param: p",
+// but *not* "leaking param: p to result r level=0".
+func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r"
+       sink4 = &r
+       return p
+}