modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/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:35$" "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:35$" 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:43$" "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:43$" 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:48$" "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:48$" 48 return c // "return" // ERROR "c escapes to heap$" "from ~r1 \(return\) at escape_because.go:48$" 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:78$" "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:81$" "from ~r2 \(return\) at escape_because.go:78$" "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: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$" 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:98$" "map\[\*int\]\*int literal escapes to heap$" 99 } 100 101 func f12() { 102 b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from b \(assigned\) at escape_because.go:102$" "from b \(passed to call\[argument escapes\]\) at escape_because.go:103$" 103 escape(b) 104 } 105 106 func escape(b []byte) { // ERROR "from panic\(b\) \(panic\) at escape_because.go:107$" "leaking param: b$" 107 panic(b) 108 } 109 110 func f13() { 111 b := []byte("test") // ERROR "\(\[\]byte\)\(.test.\) escapes to heap$" "from .out0 \(passed-to-and-returned-from-call\) at escape_because.go:112$" "from b \(assigned\) at escape_because.go:111$" "from c \(assigned\) at escape_because.go:112$" "from c \(passed to call\[argument escapes\]\) at escape_because.go:113$" 112 c := transmit(b) 113 escape(c) 114 } 115 116 //go:noinline 117 func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because.go:118$" "leaking param: b to result ~r1 level=0$" 118 return b 119 } 120 121 // The list below is all of the why-escapes messages seen building the escape analysis tests. 122 /* 123 for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done 124 grep 'from .* at ' escape*.log | sed -e 's/^.*(\([^()]*\))[^()]*$/\1/' | sort -u 125 */ 126 // sed RE above assumes that (reason) is the last parenthesized phrase in the line, 127 // and that none of the reasons contains any parentheses 128 129 /* 130 ... arg to recursive call 131 address-of 132 appended slice... 133 appended to slice 134 appendee slice 135 arg to ... 136 arg to recursive call 137 array literal element 138 array-element-equals 139 assign-pair 140 assign-pair-dot-type 141 assign-pair-func-call 142 assigned 143 assigned to top level variable 144 call part 145 captured by a closure 146 closure-var 147 converted 148 copied slice 149 defer func 150 defer func ... 151 defer func arg 152 dot 153 dot of pointer 154 dot-equals 155 fixed-array-index-of 156 go func 157 go func ... 158 go func arg 159 indirection 160 interface-converted 161 key of map put 162 map literal key 163 map literal value 164 parameter to indirect call 165 passed to call[argument content escapes] 166 passed to call[argument escapes] 167 passed-to-and-returned-from-call 168 pointer literal 169 range 170 range-deref 171 receiver in indirect call 172 return 173 returned from recursive function 174 send 175 slice 176 slice-element-equals 177 slice-literal-element 178 star-dot-equals 179 star-equals 180 struct literal element 181 switch case 182 too large for stack 183 value of map put 184 */ 185 186 // Expected, but not yet seen (they may be unreachable): 187 188 /* 189 append-first-arg 190 assign-pair-mapr 191 assign-pair-receive 192 call receiver 193 map index 194 panic 195 pointer literal [assign] 196 slice literal element 197 */