blob: bd6c025476ee8a8ddaff4933b715aa9bf999f2c8 [file] [log] [blame]
Matthew Dempsky501b7862019-07-25 12:54:03 -07001// errorcheck -0 -m -l
Dmitry Vyukov8a254572015-02-19 15:57:03 +03002
Emmanuel Odeke53fd5222016-04-10 14:32:26 -07003// Copyright 2015 The Go Authors. All rights reserved.
Dmitry Vyukov8a254572015-02-19 15:57:03 +03004// 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() {
Matthew Dempskya9831632019-04-02 14:44:13 -070014 x := 0
Dmitry Vyukov8a254572015-02-19 15:57:03 +030015 func(p *int) { // ERROR "p does not escape" "func literal does not escape"
16 *p = 1
Matthew Dempskyabefcac2019-04-01 11:58:33 -070017 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030018}
19
20func ClosureCallArgs1() {
Matthew Dempskya9831632019-04-02 14:44:13 -070021 x := 0
Dmitry Vyukov8a254572015-02-19 15:57:03 +030022 for {
23 func(p *int) { // ERROR "p does not escape" "func literal does not escape"
24 *p = 1
Matthew Dempskyabefcac2019-04-01 11:58:33 -070025 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030026 }
27}
28
29func ClosureCallArgs2() {
30 for {
Matthew Dempskya9831632019-04-02 14:44:13 -070031 x := 0
Dmitry Vyukov8a254572015-02-19 15:57:03 +030032 func(p *int) { // ERROR "p does not escape" "func literal does not escape"
33 *p = 1
Matthew Dempskyabefcac2019-04-01 11:58:33 -070034 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030035 }
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"
Matthew Dempsky9f89edc2019-08-30 10:56:30 -070041 sink = p
Matthew Dempskyabefcac2019-04-01 11:58:33 -070042 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030043}
44
45func ClosureCallArgs4() {
Matthew Dempskya9831632019-04-02 14:44:13 -070046 x := 0
Matthew Dempskye99e9a62021-05-26 13:54:31 -070047 _ = func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape"
Dmitry Vyukov8a254572015-02-19 15:57:03 +030048 return p
Matthew Dempskyabefcac2019-04-01 11:58:33 -070049 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030050}
51
52func ClosureCallArgs5() {
Matthew Dempskyc0417df2020-09-22 02:12:03 -070053 x := 0 // ERROR "moved to heap: x"
Matthew Dempskya9831632019-04-02 14:44:13 -070054 // 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.
Matthew Dempsky9f89edc2019-08-30 10:56:30 -070056 sink = func(p *int) *int { // ERROR "leaking param: p" "func literal does not escape"
Dmitry Vyukov8a254572015-02-19 15:57:03 +030057 return p
Matthew Dempskyabefcac2019-04-01 11:58:33 -070058 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030059}
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"
Matthew Dempsky9f89edc2019-08-30 10:56:30 -070064 sink = &p
Matthew Dempskyabefcac2019-04-01 11:58:33 -070065 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030066}
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
Matthew Dempskyabefcac2019-04-01 11:58:33 -070074 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030075 }
76 _ = pp
77}
78
79func ClosureCallArgs8() {
Matthew Dempskya9831632019-04-02 14:44:13 -070080 x := 0
Dmitry Vyukov8a254572015-02-19 15:57:03 +030081 defer func(p *int) { // ERROR "p does not escape" "func literal does not escape"
82 *p = 1
Matthew Dempskyabefcac2019-04-01 11:58:33 -070083 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030084}
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
Matthew Dempskyabefcac2019-04-01 11:58:33 -070092 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +030093 }
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
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700101 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300102 }
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"
Matthew Dempsky9f89edc2019-08-30 10:56:30 -0700108 sink = p
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700109 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300110}
111
112func ClosureCallArgs12() {
Matthew Dempskya9831632019-04-02 14:44:13 -0700113 x := 0
Matthew Dempskye99e9a62021-05-26 13:54:31 -0700114 defer func(p *int) *int { // ERROR "leaking param: p to result ~r0" "func literal does not escape"
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300115 return p
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700116 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300117}
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"
Matthew Dempsky9f89edc2019-08-30 10:56:30 -0700122 sink = &p
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700123 }(&x)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300124}
125
126func ClosureCallArgs14() {
Matthew Dempskya9831632019-04-02 14:44:13 -0700127 x := 0
128 p := &x
Matthew Dempskye99e9a62021-05-26 13:54:31 -0700129 _ = func(p **int) *int { // ERROR "leaking param: p to result ~r0 level=1" "func literal does not escape"
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300130 return *p
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700131 }(&p)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300132}
133
134func ClosureCallArgs15() {
Matthew Dempskyc0417df2020-09-22 02:12:03 -0700135 x := 0 // ERROR "moved to heap: x"
Matthew Dempskya9831632019-04-02 14:44:13 -0700136 p := &x
Matthew Dempsky9f89edc2019-08-30 10:56:30 -0700137 sink = func(p **int) *int { // ERROR "leaking param content: p" "func literal does not escape"
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300138 return *p
Matthew Dempskyabefcac2019-04-01 11:58:33 -0700139 }(&p)
Dmitry Vyukov8a254572015-02-19 15:57:03 +0300140}
David Chased8c815d2016-03-01 16:53:37 -0500141
Matthew Dempsky606019c2019-09-12 10:18:03 -0700142func ClosureLeak1(s string) string { // ERROR "s does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500143 t := s + "YYYY" // ERROR "escapes to heap"
Matthew Dempsky606019c2019-09-12 10:18:03 -0700144 return ClosureLeak1a(t) // ERROR "... argument does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500145}
146
147// See #14409 -- returning part of captured var leaks it.
Matthew Dempskye99e9a62021-05-26 13:54:31 -0700148func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r0 level=1$"
Matthew Dempsky606019c2019-09-12 10:18:03 -0700149 return func() string { // ERROR "func literal does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500150 return a[0]
151 }()
152}
153
Matthew Dempsky606019c2019-09-12 10:18:03 -0700154func ClosureLeak2(s string) string { // ERROR "s does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500155 t := s + "YYYY" // ERROR "escapes to heap"
Matthew Dempsky606019c2019-09-12 10:18:03 -0700156 c := ClosureLeak2a(t) // ERROR "... argument does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500157 return c
158}
Matthew Dempskya9831632019-04-02 14:44:13 -0700159func ClosureLeak2a(a ...string) string { // ERROR "leaking param content: a"
Matthew Dempsky606019c2019-09-12 10:18:03 -0700160 return ClosureLeak2b(func() string { // ERROR "func literal does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500161 return a[0]
162 })
163}
Matthew Dempsky606019c2019-09-12 10:18:03 -0700164func ClosureLeak2b(f func() string) string { // ERROR "f does not escape"
David Chased8c815d2016-03-01 16:53:37 -0500165 return f()
166}
Matthew Dempskyc0417df2020-09-22 02:12:03 -0700167
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"