Home | History | Annotate | Download | only in test
      1 // errorcheck -0 -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 // Test escape analysis for function parameters.
      8 
      9 // In this test almost everything is BAD except the simplest cases
     10 // where input directly flows to output.
     11 
     12 package escape
     13 
     14 var sink interface{}
     15 
     16 // in -> out
     17 func param0(p *int) *int { // ERROR "leaking param: p to result ~r1"
     18 	return p
     19 }
     20 
     21 func caller0a() {
     22 	i := 0
     23 	_ = param0(&i) // ERROR "caller0a &i does not escape$"
     24 }
     25 
     26 func caller0b() {
     27 	i := 0            // ERROR "moved to heap: i$"
     28 	sink = param0(&i) // ERROR "&i escapes to heap$" "param0\(&i\) escapes to heap"
     29 }
     30 
     31 // in, in -> out, out
     32 func param1(p1, p2 *int) (*int, *int) { // ERROR "leaking param: p1 to result ~r2" "leaking param: p2 to result ~r3"
     33 	return p1, p2
     34 }
     35 
     36 func caller1() {
     37 	i := 0 // ERROR "moved to heap: i$"
     38 	j := 0
     39 	sink, _ = param1(&i, &j) // ERROR "&i escapes to heap$" "caller1 &j does not escape$"
     40 }
     41 
     42 // in -> other in
     43 func param2(p1 *int, p2 **int) { // ERROR "leaking param: p1$" "param2 p2 does not escape$"
     44 	*p2 = p1
     45 }
     46 
     47 func caller2a() {
     48 	i := 0 // ERROR "moved to heap: i$"
     49 	var p *int
     50 	param2(&i, &p) // ERROR "&i escapes to heap$" "caller2a &p does not escape$"
     51 	_ = p
     52 }
     53 
     54 func caller2b() {
     55 	i := 0 // ERROR "moved to heap: i$"
     56 	var p *int
     57 	param2(&i, &p) // ERROR "&i escapes to heap$" "caller2b &p does not escape$"
     58 	sink = p       // ERROR "p escapes to heap$"
     59 }
     60 
     61 // in -> in
     62 type Pair struct {
     63 	p1 *int
     64 	p2 *int
     65 }
     66 
     67 func param3(p *Pair) { // ERROR "leaking param content: p$"
     68 	p.p1 = p.p2
     69 }
     70 
     71 func caller3a() {
     72 	i := 0            // ERROR "moved to heap: i$"
     73 	j := 0            // ERROR "moved to heap: j$"
     74 	p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
     75 	param3(&p)        // ERROR "caller3a &p does not escape"
     76 	_ = p
     77 }
     78 
     79 func caller3b() {
     80 	i := 0            // ERROR "moved to heap: i$"
     81 	j := 0            // ERROR "moved to heap: j$"
     82 	p := Pair{&i, &j} // ERROR "&i escapes to heap$" "&j escapes to heap$"
     83 	param3(&p)        // ERROR "caller3b &p does not escape"
     84 	sink = p          // ERROR "p escapes to heap$"
     85 }
     86 
     87 // in -> rcvr
     88 func (p *Pair) param4(i *int) { // ERROR "\(\*Pair\).param4 p does not escape$" "leaking param: i$"
     89 	p.p1 = i
     90 }
     91 
     92 func caller4a() {
     93 	i := 0 // ERROR "moved to heap: i$"
     94 	p := Pair{}
     95 	p.param4(&i) // ERROR "&i escapes to heap$" "caller4a p does not escape$"
     96 	_ = p
     97 }
     98 
     99 func caller4b() {
    100 	i := 0 // ERROR "moved to heap: i$"
    101 	p := Pair{}
    102 	p.param4(&i) // ERROR "&i escapes to heap$" "caller4b p does not escape$"
    103 	sink = p     // ERROR "p escapes to heap$"
    104 }
    105 
    106 // in -> heap
    107 func param5(i *int) { // ERROR "leaking param: i$"
    108 	sink = i // ERROR "i escapes to heap$"
    109 }
    110 
    111 func caller5() {
    112 	i := 0     // ERROR "moved to heap: i$"
    113 	param5(&i) // ERROR "&i escapes to heap$"
    114 }
    115 
    116 // *in -> heap
    117 func param6(i ***int) { // ERROR "leaking param content: i$"
    118 	sink = *i // ERROR "\*i escapes to heap$"
    119 }
    120 
    121 func caller6a() {
    122 	i := 0      // ERROR "moved to heap: i$"
    123 	p := &i     // ERROR "&i escapes to heap$" "moved to heap: p$"
    124 	p2 := &p    // ERROR "&p escapes to heap$"
    125 	param6(&p2) // ERROR "caller6a &p2 does not escape"
    126 }
    127 
    128 // **in -> heap
    129 func param7(i ***int) { // ERROR "leaking param content: i$"
    130 	sink = **i // ERROR "\* \(\*i\) escapes to heap"
    131 }
    132 
    133 func caller7() {
    134 	i := 0      // ERROR "moved to heap: i$"
    135 	p := &i     // ERROR "&i escapes to heap$" "moved to heap: p$"
    136 	p2 := &p    // ERROR "&p escapes to heap$"
    137 	param7(&p2) // ERROR "caller7 &p2 does not escape"
    138 }
    139 
    140 // **in -> heap
    141 func param8(i **int) { // ERROR "param8 i does not escape$"
    142 	sink = **i // ERROR "\* \(\*i\) escapes to heap"
    143 }
    144 
    145 func caller8() {
    146 	i := 0
    147 	p := &i    // ERROR "caller8 &i does not escape$"
    148 	param8(&p) // ERROR "caller8 &p does not escape$"
    149 }
    150 
    151 // *in -> out
    152 func param9(p ***int) **int { // ERROR "leaking param: p to result ~r1 level=1"
    153 	return *p
    154 }
    155 
    156 func caller9a() {
    157 	i := 0
    158 	p := &i         // ERROR "caller9a &i does not escape"
    159 	p2 := &p        // ERROR "caller9a &p does not escape"
    160 	_ = param9(&p2) // ERROR "caller9a &p2 does not escape$"
    161 }
    162 
    163 func caller9b() {
    164 	i := 0             // ERROR "moved to heap: i$"
    165 	p := &i            // ERROR "&i escapes to heap$" "moved to heap: p$"
    166 	p2 := &p           // ERROR "&p escapes to heap$"
    167 	sink = param9(&p2) // ERROR "caller9b &p2 does not escape$"  "param9\(&p2\) escapes to heap"
    168 }
    169 
    170 // **in -> out
    171 func param10(p ***int) *int { // ERROR "leaking param: p to result ~r1 level=2"
    172 	return **p
    173 }
    174 
    175 func caller10a() {
    176 	i := 0
    177 	p := &i          // ERROR "caller10a &i does not escape"
    178 	p2 := &p         // ERROR "caller10a &p does not escape"
    179 	_ = param10(&p2) // ERROR "caller10a &p2 does not escape$"
    180 }
    181 
    182 func caller10b() {
    183 	i := 0              // ERROR "moved to heap: i$"
    184 	p := &i             // ERROR "&i escapes to heap$"
    185 	p2 := &p            // ERROR "caller10b &p does not escape$"
    186 	sink = param10(&p2) // ERROR "caller10b &p2 does not escape$" "param10\(&p2\) escapes to heap"
    187 }
    188 
    189 // in escapes to heap (address of param taken and returned)
    190 func param11(i **int) ***int { // ERROR "moved to heap: i$"
    191 	return &i // ERROR "&i escapes to heap$"
    192 }
    193 
    194 func caller11a() {
    195 	i := 0          // ERROR "moved to heap: i"
    196 	p := &i         // ERROR "moved to heap: p" "&i escapes to heap"
    197 	_ = param11(&p) // ERROR "&p escapes to heap"
    198 }
    199 
    200 func caller11b() {
    201 	i := 0             // ERROR "moved to heap: i$"
    202 	p := &i            // ERROR "&i escapes to heap$" "moved to heap: p$"
    203 	sink = param11(&p) // ERROR "&p escapes to heap$" "param11\(&p\) escapes to heap"
    204 }
    205 
    206 func caller11c() { // GOOD
    207 	i := 0              // ERROR "moved to heap: i$"
    208 	p := &i             // ERROR "moved to heap: p" "&i escapes to heap"
    209 	sink = *param11(&p) // ERROR "&p escapes to heap" "\*param11\(&p\) escapes to heap"
    210 }
    211 
    212 func caller11d() {
    213 	i := 0             // ERROR "moved to heap: i$"
    214 	p := &i            // ERROR "&i escapes to heap" "moved to heap: p"
    215 	p2 := &p           // ERROR "&p escapes to heap"
    216 	sink = param11(p2) // ERROR "param11\(p2\) escapes to heap"
    217 }
    218 
    219 // &in -> rcvr
    220 type Indir struct {
    221 	p ***int
    222 }
    223 
    224 func (r *Indir) param12(i **int) { // ERROR "\(\*Indir\).param12 r does not escape$" "moved to heap: i$"
    225 	r.p = &i // ERROR "&i escapes to heap$"
    226 }
    227 
    228 func caller12a() {
    229 	i := 0  // ERROR "moved to heap: i$"
    230 	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
    231 	var r Indir
    232 	r.param12(&p) // ERROR "&p escapes to heap$" "caller12a r does not escape$"
    233 	_ = r
    234 }
    235 
    236 func caller12b() {
    237 	i := 0        // ERROR "moved to heap: i$"
    238 	p := &i       // ERROR "&i escapes to heap$" "moved to heap: p$"
    239 	r := &Indir{} // ERROR "caller12b &Indir literal does not escape$"
    240 	r.param12(&p) // ERROR "&p escapes to heap$"
    241 	_ = r
    242 }
    243 
    244 func caller12c() {
    245 	i := 0  // ERROR "moved to heap: i$"
    246 	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
    247 	r := Indir{}
    248 	r.param12(&p) // ERROR "&p escapes to heap$" "caller12c r does not escape$"
    249 	sink = r      // ERROR "r escapes to heap$"
    250 }
    251 
    252 func caller12d() {
    253 	i := 0  // ERROR "moved to heap: i$"
    254 	p := &i // ERROR "&i escapes to heap$" "moved to heap: p$"
    255 	r := Indir{}
    256 	r.param12(&p) // ERROR "&p escapes to heap$" "caller12d r does not escape$"
    257 	sink = **r.p  // ERROR "\* \(\*r\.p\) escapes to heap"
    258 }
    259 
    260 // in -> value rcvr
    261 type Val struct {
    262 	p **int
    263 }
    264 
    265 func (v Val) param13(i *int) { // ERROR "Val.param13 v does not escape$" "leaking param: i$"
    266 	*v.p = i
    267 }
    268 
    269 func caller13a() {
    270 	i := 0 // ERROR "moved to heap: i$"
    271 	var p *int
    272 	var v Val
    273 	v.p = &p      // ERROR "caller13a &p does not escape$"
    274 	v.param13(&i) // ERROR "&i escapes to heap$"
    275 	_ = v
    276 }
    277 
    278 func caller13b() {
    279 	i := 0 // ERROR "moved to heap: i$"
    280 	var p *int
    281 	v := Val{&p}  // ERROR "caller13b &p does not escape$"
    282 	v.param13(&i) // ERROR "&i escapes to heap$"
    283 	_ = v
    284 }
    285 
    286 func caller13c() {
    287 	i := 0 // ERROR "moved to heap: i$"
    288 	var p *int
    289 	v := &Val{&p} // ERROR "caller13c &Val literal does not escape$" "caller13c &p does not escape$"
    290 	v.param13(&i) // ERROR "&i escapes to heap$"
    291 	_ = v
    292 }
    293 
    294 func caller13d() {
    295 	i := 0     // ERROR "moved to heap: i$"
    296 	var p *int // ERROR "moved to heap: p$"
    297 	var v Val
    298 	v.p = &p      // ERROR "&p escapes to heap$"
    299 	v.param13(&i) // ERROR "&i escapes to heap$"
    300 	sink = v      // ERROR "v escapes to heap$"
    301 }
    302 
    303 func caller13e() {
    304 	i := 0        // ERROR "moved to heap: i$"
    305 	var p *int    // ERROR "moved to heap: p$"
    306 	v := Val{&p}  // ERROR "&p escapes to heap$"
    307 	v.param13(&i) // ERROR "&i escapes to heap$"
    308 	sink = v      // ERROR "v escapes to heap$"
    309 }
    310 
    311 func caller13f() {
    312 	i := 0        // ERROR "moved to heap: i$"
    313 	var p *int    // ERROR "moved to heap: p$"
    314 	v := &Val{&p} // ERROR "&Val literal escapes to heap$" "&p escapes to heap$"
    315 	v.param13(&i) // ERROR "&i escapes to heap$"
    316 	sink = v      // ERROR "v escapes to heap$"
    317 }
    318 
    319 func caller13g() {
    320 	i := 0 // ERROR "moved to heap: i$"
    321 	var p *int
    322 	v := Val{&p}  // ERROR "caller13g &p does not escape$"
    323 	v.param13(&i) // ERROR "&i escapes to heap$"
    324 	sink = *v.p   // ERROR "\*v\.p escapes to heap"
    325 }
    326 
    327 func caller13h() {
    328 	i := 0 // ERROR "moved to heap: i$"
    329 	var p *int
    330 	v := &Val{&p} // ERROR "caller13h &Val literal does not escape$" "caller13h &p does not escape$"
    331 	v.param13(&i) // ERROR "&i escapes to heap$"
    332 	sink = **v.p  // ERROR "\* \(\*v\.p\) escapes to heap"
    333 }
    334 
    335 type Node struct {
    336 	p *Node
    337 }
    338 
    339 var Sink *Node
    340 
    341 func f(x *Node) { // ERROR "leaking param content: x"
    342 	Sink = &Node{x.p} // ERROR "&Node literal escapes to heap"
    343 }
    344 
    345 func g(x *Node) *Node { // ERROR "leaking param: x to result ~r1 level=0"
    346 	return &Node{x.p} // ERROR "&Node literal escapes to heap"
    347 }
    348 
    349 func h(x *Node) { // ERROR "leaking param: x"
    350 	y := &Node{x} // ERROR "h &Node literal does not escape"
    351 	Sink = g(y)
    352 	f(y)
    353 }
    354