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 closure arguments. 8 9package escape 10 11var sink interface{} 12 13func ClosureCallArgs0() { 14 x := 0 15 func(p *int) { // ERROR "p does not escape" "func literal does not escape" 16 *p = 1 17 }(&x) 18} 19 20func ClosureCallArgs1() { 21 x := 0 22 for { 23 func(p *int) { // ERROR "p does not escape" "func literal does not escape" 24 *p = 1 25 }(&x) 26 } 27} 28 29func ClosureCallArgs2() { 30 for { 31 x := 0 32 func(p *int) { // ERROR "p does not escape" "func literal does not escape" 33 *p = 1 34 }(&x) 35 } 36} 37 38func ClosureCallArgs3() { 39 x := 0 // ERROR "moved to heap: x" 40 func(p *int) { // ERROR "leaking param: p" "func literal does not escape" 41 sink = p 42 }(&x) 43} 44 45func ClosureCallArgs4() { 46 x := 0 47 _ = func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape" 48 return p 49 }(&x) 50} 51 52func ClosureCallArgs5() { 53 x := 0 // ERROR "moved to heap: x" 54 // TODO(mdempsky): We get "leaking param: p" here because the new escape analysis pass 55 // can tell that p flows directly to sink, but it's a little weird. Re-evaluate. 56 sink = func(p *int) *int { // ERROR "leaking param: p" "func literal does not escape" 57 return p 58 }(&x) 59} 60 61func ClosureCallArgs6() { 62 x := 0 // ERROR "moved to heap: x" 63 func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" 64 sink = &p 65 }(&x) 66} 67 68func ClosureCallArgs7() { 69 var pp *int 70 for { 71 x := 0 // ERROR "moved to heap: x" 72 func(p *int) { // ERROR "leaking param: p" "func literal does not escape" 73 pp = p 74 }(&x) 75 } 76 _ = pp 77} 78 79func ClosureCallArgs8() { 80 x := 0 81 defer func(p *int) { // ERROR "p does not escape" "func literal does not escape" 82 *p = 1 83 }(&x) 84} 85 86func ClosureCallArgs9() { 87 // BAD: x should not leak 88 x := 0 // ERROR "moved to heap: x" 89 for { 90 defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" 91 *p = 1 92 }(&x) 93 } 94} 95 96func ClosureCallArgs10() { 97 for { 98 x := 0 // ERROR "moved to heap: x" 99 defer func(p *int) { // ERROR "func literal escapes to heap" "p does not escape" 100 *p = 1 101 }(&x) 102 } 103} 104 105func ClosureCallArgs11() { 106 x := 0 // ERROR "moved to heap: x" 107 defer func(p *int) { // ERROR "leaking param: p" "func literal does not escape" 108 sink = p 109 }(&x) 110} 111 112func ClosureCallArgs12() { 113 x := 0 114 defer func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape" 115 return p 116 }(&x) 117} 118 119func ClosureCallArgs13() { 120 x := 0 // ERROR "moved to heap: x" 121 defer func(p *int) { // ERROR "moved to heap: p" "func literal does not escape" 122 sink = &p 123 }(&x) 124} 125 126func ClosureCallArgs14() { 127 x := 0 128 p := &x 129 _ = func(p **int) *int { // ERROR "leaking param: p to result ~r0 level=1" "func literal does not escape" 130 return *p 131 }(&p) 132} 133 134func ClosureCallArgs15() { 135 x := 0 // ERROR "moved to heap: x" 136 p := &x 137 sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape" 138 return *p 139 }(&p) 140} 141 142func ClosureLeak1(s string) string { // ERROR "s does not escape" 143 t := s + "YYYY" // ERROR "escapes to heap" 144 return ClosureLeak1a(t) // ERROR "... argument does not escape" 145} 146 147// See #14409 -- returning part of captured var leaks it. 148func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r0 level=1$" 149 return func() string { // ERROR "func literal does not escape" 150 return a[0] 151 }() 152} 153 154func ClosureLeak2(s string) string { // ERROR "s does not escape" 155 t := s + "YYYY" // ERROR "escapes to heap" 156 c := ClosureLeak2a(t) // ERROR "... argument does not escape" 157 return c 158} 159func ClosureLeak2a(a ...string) string { // ERROR "leaking param content: a" 160 return ClosureLeak2b(func() string { // ERROR "func literal does not escape" 161 return a[0] 162 }) 163} 164func ClosureLeak2b(f func() string) string { // ERROR "f does not escape" 165 return f() 166} 167 168func ClosureIndirect() { 169 f := func(p *int) {} // ERROR "p does not escape" "func literal does not escape" 170 f(new(int)) // ERROR "new\(int\) does not escape" 171 172 g := f 173 g(new(int)) // ERROR "new\(int\) does not escape" 174 175 h := nopFunc 176 h(new(int)) // ERROR "new\(int\) does not escape" 177} 178 179func nopFunc(p *int) {} // ERROR "p does not escape" 180 181func ClosureIndirect2() { 182 f := func(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0" "func literal does not escape" 183 184 f(new(int)) // ERROR "new\(int\) does not escape" 185 186 g := f 187 g(new(int)) // ERROR "new\(int\) does not escape" 188 189 h := nopFunc2 190 h(new(int)) // ERROR "new\(int\) does not escape" 191} 192 193func nopFunc2(p *int) *int { return p } // ERROR "leaking param: p to result ~r0 level=0" 194