github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/test/escape_because.go (about) 1 // errorcheck -0 -m -m -l 2 3 // Copyright 2015 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Note the doubled -m; this tests the "because" explanations for escapes, 8 // and is likely to be annoyingly fragile under compiler change. 9 // As long as the explanations look reasonably sane, meaning eyeball verify output of 10 // go build -gcflags '-l -m -m' escape_because.go 11 // and investigate changes, feel free to update with 12 // go run run.go -update_errors -- escape_because.go 13 14 package main 15 16 func main() { 17 } 18 19 var sink interface{} 20 21 type pair struct { 22 x, y *int 23 } 24 25 type Pairy interface { 26 EqualParts() bool 27 } 28 29 func (p *pair) EqualParts() bool { // ERROR "\(\*pair\).EqualParts p does not escape$" 30 return p != nil && (p.x == p.y || *p.x == *p.y) 31 } 32 33 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:19$" "leaking param: p$" 34 a := [3]*int{p, nil, nil} 35 sink = a // ERROR "a escapes to heap$" "from sink \(assigned to top level variable\) at escape_because.go:19$" 36 37 } 38 39 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:19$" "from t \(assigned\) at escape_because.go:41$" "from u \(assigned\) at escape_because.go:42$" "leaking param: q$" 40 s := q 41 t := pair{s, nil} 42 u := t // ERROR "moved to heap: u$" 43 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:19$" 44 } 45 46 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:46$" "leaking param: r to result ~r1 level=-1$" 47 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:46$" 48 return c // "return" // ERROR "c escapes to heap$" "from ~r1 \(return\) at escape_because.go:46$" 49 } 50 51 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$" 52 s = append(s, a) 53 return *(s[0]) 54 } 55 56 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$" 57 s1 = append(s1, s2...) 58 return *(s1[0]) 59 } 60 61 func f6(x, y *int) bool { // ERROR "f6 x does not escape$" "f6 y does not escape$" 62 p := pair{x, y} 63 var P Pairy = &p // ERROR "f6 &p does not escape$" 64 pp := P.(*pair) 65 return pp.EqualParts() 66 } 67 68 func f7(x map[int]*int, y int) *int { // ERROR "f7 x does not escape$" 69 z, ok := x[y] 70 if !ok { 71 return nil 72 } 73 return z 74 } 75 76 func f8(x int, y *int) *int { // ERROR "from ~r2 \(return\) at escape_because.go:76$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$" "leaking param: y$" "moved to heap: x$" 77 if x <= 0 { 78 return y 79 } 80 x-- 81 return f8(*y, &x) // ERROR "&x escapes to heap$" "from y \(arg to recursive call\) at escape_because.go:76$" "from ~r2 \(return\) at escape_because.go:76$" "from ~r2 \(returned from recursive function\) at escape_because.go:76$" 82 } 83 84 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:84$" "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$" 85 if x <= 0 { 86 return y[0] 87 } 88 x-- 89 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$" 90 } 91 92 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$" 93 x[y] = z 94 return z 95 } 96 97 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$" 98 return map[*int]*int{y: z} // ERROR "from ~r3 \(return\) at escape_because.go:97$" "map\[\*int\]\*int literal escapes to heap$" 99 } 100 101 // The list below is all of the why-escapes messages seen building the escape analysis tests. 102 /* 103 for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done 104 grep 'from .* at ' escape*.log | sed -e 's/^.*(\([^()]*\))[^()]*$/\1/' | sort -u 105 */ 106 // sed RE above assumes that (reason) is the last parenthesized phrase in the line, 107 // and that none of the reasons contains any parentheses 108 109 /* 110 ... arg to recursive call 111 address-of 112 appended slice... 113 appended to slice 114 appendee slice 115 arg to ... 116 arg to recursive call 117 array literal element 118 array-element-equals 119 assign-pair 120 assign-pair-dot-type 121 assign-pair-func-call 122 assigned 123 assigned to top level variable 124 call part 125 captured by a closure 126 closure-var 127 converted 128 copied slice 129 defer func 130 defer func ... 131 defer func arg 132 dot 133 dot of pointer 134 dot-equals 135 fixed-array-index-of 136 go func 137 go func ... 138 go func arg 139 indirection 140 interface-converted 141 key of map put 142 map literal key 143 map literal value 144 parameter to indirect call 145 passed to function[content escapes] 146 passed to function[unknown] 147 passed-to-and-returned-from-function 148 pointer literal 149 range 150 range-deref 151 receiver in indirect call 152 return 153 returned from recursive function 154 send 155 slice 156 slice-element-equals 157 slice-literal-element 158 star-dot-equals 159 star-equals 160 struct literal element 161 switch case 162 too large for stack 163 value of map put 164 */ 165 166 // Expected, but not yet seen (they may be unreachable): 167 168 /* 169 append-first-arg 170 assign-pair-mapr 171 assign-pair-receive 172 call receiver 173 map index 174 panic 175 pointer literal [assign] 176 slice literal element 177 */