]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape5.go
[dev.typeparams] all: merge master (785a8f6) into dev.typeparams
[gostls13.git] / test / escape5.go
1 // errorcheck -0 -m -l
2
3 // Copyright 2012 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, using compiler diagnostic flags, that the escape analysis is working.
8 // Compiles but does not run.  Inlining is disabled.
9
10 package foo
11
12 import (
13         "runtime"
14         "unsafe"
15 )
16
17 func noleak(p *int) int { // ERROR "p does not escape"
18         return *p
19 }
20
21 func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
22         return p
23 }
24
25 func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: p to result ~r1"
26         return p, p
27 }
28
29 func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r0" "leaking param: q to result ~r1"
30         return p, q
31 }
32
33 func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0"
34         return leaktoret22(q, p)
35 }
36
37 func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: q to result ~r0"
38         r, s := leaktoret22(q, p)
39         return r, s
40 }
41
42 func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
43         r, s = leaktoret22(q, p)
44         return
45 }
46
47 func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
48         r, s = leaktoret22(q, p)
49         return r, s
50 }
51
52 func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
53         rr, ss := leaktoret22(q, p)
54         return rr, ss
55 }
56
57 var gp *int
58
59 func leaktosink(p *int) *int { // ERROR "leaking param: p"
60         gp = p
61         return p
62 }
63
64 func f1() {
65         var x int
66         p := noleak(&x)
67         _ = p
68 }
69
70 func f2() {
71         var x int
72         p := leaktoret(&x)
73         _ = p
74 }
75
76 func f3() {
77         var x int // ERROR "moved to heap: x"
78         p := leaktoret(&x)
79         gp = p
80 }
81
82 func f4() {
83         var x int // ERROR "moved to heap: x"
84         p, q := leaktoret2(&x)
85         gp = p
86         gp = q
87 }
88
89 func f5() {
90         var x int
91         leaktoret22(leaktoret2(&x))
92 }
93
94 func f6() {
95         var x int // ERROR "moved to heap: x"
96         px1, px2 := leaktoret22(leaktoret2(&x))
97         gp = px1
98         _ = px2
99 }
100
101 type T struct{ x int }
102
103 func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
104         t.x += u
105         return t, true
106 }
107
108 func f7() *T {
109         r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
110         return r
111 }
112
113 func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
114         return leakrecursive2(q, p)
115 }
116
117 func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
118         if *p > *q {
119                 return leakrecursive1(q, p)
120         }
121         // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
122         return p, q
123 }
124
125 var global interface{}
126
127 type T1 struct {
128         X *int
129 }
130
131 type T2 struct {
132         Y *T1
133 }
134
135 func f8(p *T1) (k T2) { // ERROR "leaking param: p$"
136         if p == nil {
137                 k = T2{}
138                 return
139         }
140
141         // should make p leak always
142         global = p
143         return T2{p}
144 }
145
146 func f9() {
147         var j T1 // ERROR "moved to heap: j"
148         f8(&j)
149 }
150
151 func f10() {
152         // These don't escape but are too big for the stack
153         var x [1 << 30]byte         // ERROR "moved to heap: x"
154         var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
155         _ = x[0] + y[0]
156 }
157
158 // Test for issue 19687 (passing to unnamed parameters does not escape).
159 func f11(**int) {
160 }
161 func f12(_ **int) {
162 }
163 func f13() {
164         var x *int
165         f11(&x)
166         f12(&x)
167         runtime.KeepAlive(&x)
168 }
169
170 // Test for issue 24305 (passing to unnamed receivers does not escape).
171 type U int
172
173 func (*U) M()   {}
174 func (_ *U) N() {}
175
176 func _() {
177         var u U
178         u.M()
179         u.N()
180 }
181
182 func fbad24305() {
183         // BAD u should not be heap allocated
184         var u U // ERROR "moved to heap: u"
185         (*U).M(&u)
186         (*U).N(&u)
187 }
188
189 // Issue 24730: taking address in a loop causes unnecessary escape
190 type T24730 struct {
191         x [64]byte
192 }
193
194 func (t *T24730) g() { // ERROR "t does not escape"
195         y := t.x[:]
196         for i := range t.x[:] {
197                 y = t.x[:]
198                 y[i] = 1
199         }
200
201         var z *byte
202         for i := range t.x[:] {
203                 z = &t.x[i]
204                 *z = 2
205         }
206 }
207
208 // Issue 15730: copy causes unnecessary escape
209
210 var sink []byte
211 var sink2 []int
212 var sink3 []*int
213
214 func f15730a(args ...interface{}) { // ERROR "args does not escape"
215         for _, arg := range args {
216                 switch a := arg.(type) {
217                 case string:
218                         copy(sink, a)
219                 }
220         }
221 }
222
223 func f15730b(args ...interface{}) { // ERROR "args does not escape"
224         for _, arg := range args {
225                 switch a := arg.(type) {
226                 case []int:
227                         copy(sink2, a)
228                 }
229         }
230 }
231
232 func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
233         for _, arg := range args {
234                 switch a := arg.(type) {
235                 case []*int:
236                         // copy pointerful data should cause escape
237                         copy(sink3, a)
238                 }
239         }
240 }
241
242 // Issue 29000: unnamed parameter is not handled correctly
243
244 var sink4 interface{}
245 var alwaysFalse = false
246
247 func f29000(_ int, x interface{}) { // ERROR "leaking param: x"
248         sink4 = x
249         if alwaysFalse {
250                 g29000()
251         }
252 }
253
254 func g29000() {
255         x := 1
256         f29000(2, x) // ERROR "x escapes to heap"
257 }
258
259 // Issue 28369: taking an address of a parameter and converting it into a uintptr causes an
260 // unnecessary escape.
261
262 var sink28369 uintptr
263
264 func f28369(n int) int {
265         if n == 0 {
266                 sink28369 = uintptr(unsafe.Pointer(&n))
267                 return n
268         }
269
270         return 1 + f28369(n-1)
271 }
272
273 // Issue 44614: parameters that flow to a heap-allocated result
274 // parameter must be recorded as a heap-flow rather than a
275 // result-flow.
276
277 // N.B., must match "leaking param: p",
278 // but *not* "leaking param: p to result r level=0".
279 func f(p *int) (r *int) { // ERROR "leaking param: p$" "moved to heap: r"
280         sink4 = &r
281         return p
282 }