Home | History | Annotate | Download | only in test
      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 */
    198