]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape_reflect.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / escape_reflect.go
1 // errorcheck -0 -m -l
2
3 // Copyright 2022 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 reflect Value operations.
8
9 package escape
10
11 import (
12         "reflect"
13         "unsafe"
14 )
15
16 var sink interface{}
17
18 func typ(x int) any {
19         v := reflect.ValueOf(x) // ERROR "x does not escape"
20         return v.Type()
21 }
22
23 func kind(x int) reflect.Kind {
24         v := reflect.ValueOf(x) // ERROR "x does not escape"
25         return v.Kind()
26 }
27
28 func int1(x int) int {
29         v := reflect.ValueOf(x) // ERROR "x does not escape"
30         return int(v.Int())
31 }
32
33 func ptr(x *int) *int { // ERROR "leaking param: x to result ~r0 level=0"
34         v := reflect.ValueOf(x)
35         return (*int)(v.UnsafePointer())
36 }
37
38 func bytes1(x []byte) byte { // ERROR "x does not escape"
39         v := reflect.ValueOf(x) // ERROR "x does not escape"
40         return v.Bytes()[0]
41 }
42
43 // Unfortunate: should only escape content. x (the interface storage) should not escape.
44 func bytes2(x []byte) []byte { // ERROR "leaking param: x$"
45         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
46         return v.Bytes()
47 }
48
49 func string1(x string) string { // ERROR "leaking param: x to result ~r0 level=0"
50         v := reflect.ValueOf(x) // ERROR "x does not escape"
51         return v.String()
52 }
53
54 func string2(x int) string {
55         v := reflect.ValueOf(x) // ERROR "x does not escape"
56         return v.String()
57 }
58
59 // Unfortunate: should only escape to result.
60 func interface1(x any) any { // ERROR "leaking param: x$"
61         v := reflect.ValueOf(x)
62         return v.Interface()
63 }
64
65 func interface2(x int) any {
66         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
67         return v.Interface()
68 }
69
70 // Unfortunate: should not escape.
71 func interface3(x int) int {
72         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
73         return v.Interface().(int)
74 }
75
76 // Unfortunate: should only escape to result.
77 func interface4(x *int) any { // ERROR "leaking param: x$"
78         v := reflect.ValueOf(x)
79         return v.Interface()
80 }
81
82 func addr(x *int) reflect.Value { // ERROR "leaking param: x to result ~r0 level=0"
83         v := reflect.ValueOf(x).Elem()
84         return v.Addr()
85 }
86
87 // functions returning pointer as uintptr have to escape.
88 func uintptr1(x *int) uintptr { // ERROR "leaking param: x$"
89         v := reflect.ValueOf(x)
90         return v.Pointer()
91 }
92
93 func unsafeaddr(x *int) uintptr { // ERROR "leaking param: x$"
94         v := reflect.ValueOf(x).Elem()
95         return v.UnsafeAddr()
96 }
97
98 func ifacedata(x any) [2]uintptr { // ERROR "moved to heap: x"
99         v := reflect.ValueOf(&x).Elem()
100         return v.InterfaceData()
101 }
102
103 func can(x int) bool {
104         v := reflect.ValueOf(x) // ERROR "x does not escape"
105         return v.CanAddr() || v.CanInt() || v.CanSet() || v.CanInterface()
106 }
107
108 func is(x int) bool {
109         v := reflect.ValueOf(x) // ERROR "x does not escape"
110         return v.IsValid() || v.IsNil() || v.IsZero()
111 }
112
113 func is2(x [2]int) bool {
114         v := reflect.ValueOf(x) // ERROR "x does not escape"
115         return v.IsValid() || v.IsNil() || v.IsZero()
116 }
117
118 func is3(x struct{ a, b int }) bool {
119         v := reflect.ValueOf(x) // ERROR "x does not escape"
120         return v.IsValid() || v.IsNil() || v.IsZero()
121 }
122
123 func overflow(x int) bool {
124         v := reflect.ValueOf(x) // ERROR "x does not escape"
125         return v.OverflowInt(1 << 62)
126 }
127
128 func len1(x []int) int { // ERROR "x does not escape"
129         v := reflect.ValueOf(x) // ERROR "x does not escape"
130         return v.Len()
131 }
132
133 func len2(x [3]int) int {
134         v := reflect.ValueOf(x) // ERROR "x does not escape"
135         return v.Len()
136 }
137
138 func len3(x string) int { // ERROR "x does not escape"
139         v := reflect.ValueOf(x) // ERROR "x does not escape"
140         return v.Len()
141 }
142
143 func len4(x map[int]int) int { // ERROR "x does not escape"
144         v := reflect.ValueOf(x)
145         return v.Len()
146 }
147
148 func len5(x chan int) int { // ERROR "x does not escape"
149         v := reflect.ValueOf(x)
150         return v.Len()
151 }
152
153 func cap1(x []int) int { // ERROR "x does not escape"
154         v := reflect.ValueOf(x) // ERROR "x does not escape"
155         return v.Cap()
156 }
157
158 func cap2(x [3]int) int {
159         v := reflect.ValueOf(x) // ERROR "x does not escape"
160         return v.Cap()
161 }
162
163 func cap3(x chan int) int { // ERROR "x does not escape"
164         v := reflect.ValueOf(x)
165         return v.Cap()
166 }
167
168 func setlen(x *[]int, n int) { // ERROR "x does not escape"
169         v := reflect.ValueOf(x).Elem()
170         v.SetLen(n)
171 }
172
173 func setcap(x *[]int, n int) { // ERROR "x does not escape"
174         v := reflect.ValueOf(x).Elem()
175         v.SetCap(n)
176 }
177
178 // Unfortunate: x doesn't need to escape to heap, just to result.
179 func slice1(x []byte) []byte { // ERROR "leaking param: x$"
180         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
181         return v.Slice(1, 2).Bytes()
182 }
183
184 // Unfortunate: x doesn't need to escape to heap, just to result.
185 func slice2(x string) string { // ERROR "leaking param: x$"
186         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
187         return v.Slice(1, 2).String()
188 }
189
190 func slice3(x [10]byte) []byte {
191         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
192         return v.Slice(1, 2).Bytes()
193 }
194
195 func elem1(x *int) int { // ERROR "x does not escape"
196         v := reflect.ValueOf(x)
197         return int(v.Elem().Int())
198 }
199
200 func elem2(x *string) string { // ERROR "leaking param: x to result ~r0 level=1"
201         v := reflect.ValueOf(x)
202         return string(v.Elem().String())
203 }
204
205 type S struct {
206         A int
207         B *int
208         C string
209 }
210
211 func (S) M() {}
212
213 func field1(x S) int { // ERROR "x does not escape"
214         v := reflect.ValueOf(x) // ERROR "x does not escape"
215         return int(v.Field(0).Int())
216 }
217
218 func field2(x S) string { // ERROR "leaking param: x to result ~r0 level=0"
219         v := reflect.ValueOf(x) // ERROR "x does not escape"
220         return v.Field(2).String()
221 }
222
223 func numfield(x S) int { // ERROR "x does not escape"
224         v := reflect.ValueOf(x) // ERROR "x does not escape"
225         return v.NumField()
226 }
227
228 func index1(x []int) int { // ERROR "x does not escape"
229         v := reflect.ValueOf(x) // ERROR "x does not escape"
230         return int(v.Index(0).Int())
231 }
232
233 // Unfortunate: should only leak content (level=1)
234 func index2(x []string) string { // ERROR "leaking param: x to result ~r0 level=0"
235         v := reflect.ValueOf(x) // ERROR "x does not escape"
236         return v.Index(0).String()
237 }
238
239 func index3(x [3]int) int {
240         v := reflect.ValueOf(x) // ERROR "x does not escape"
241         return int(v.Index(0).Int())
242 }
243
244 func index4(x [3]string) string { // ERROR "leaking param: x to result ~r0 level=0"
245         v := reflect.ValueOf(x) // ERROR "x does not escape"
246         return v.Index(0).String()
247 }
248
249 func index5(x string) byte { // ERROR "x does not escape"
250         v := reflect.ValueOf(x) // ERROR "x does not escape"
251         return byte(v.Index(0).Uint())
252 }
253
254 // Unfortunate: x (the interface storage) doesn't need to escape as the function takes a scalar arg.
255 func call1(f func(int), x int) { // ERROR "leaking param: f$"
256         fv := reflect.ValueOf(f)
257         v := reflect.ValueOf(x)     // ERROR "x escapes to heap"
258         fv.Call([]reflect.Value{v}) // ERROR "\[\]reflect\.Value{\.\.\.} does not escape"
259 }
260
261 func call2(f func(*int), x *int) { // ERROR "leaking param: f$" "leaking param: x$"
262         fv := reflect.ValueOf(f)
263         v := reflect.ValueOf(x)
264         fv.Call([]reflect.Value{v}) // ERROR "\[\]reflect.Value{\.\.\.} does not escape"
265 }
266
267 func method(x S) reflect.Value { // ERROR "leaking param: x$"
268         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
269         return v.Method(0)
270 }
271
272 func nummethod(x S) int { // ERROR "x does not escape"
273         v := reflect.ValueOf(x) // ERROR "x does not escape"
274         return v.NumMethod()
275 }
276
277 // Unfortunate: k doesn't need to escape.
278 func mapindex(m map[string]string, k string) string { // ERROR "m does not escape" "leaking param: k$"
279         mv := reflect.ValueOf(m)
280         kv := reflect.ValueOf(k) // ERROR "k escapes to heap"
281         return mv.MapIndex(kv).String()
282 }
283
284 func mapkeys(m map[string]string) []reflect.Value { // ERROR "m does not escape"
285         mv := reflect.ValueOf(m)
286         return mv.MapKeys()
287 }
288
289 func mapiter1(m map[string]string) *reflect.MapIter { // ERROR "leaking param: m$"
290         mv := reflect.ValueOf(m)
291         return mv.MapRange()
292 }
293
294 func mapiter2(m map[string]string) string { // ERROR "leaking param: m$"
295         mv := reflect.ValueOf(m)
296         it := mv.MapRange()
297         if it.Next() {
298                 return it.Key().String()
299         }
300         return ""
301 }
302
303 func mapiter3(m map[string]string, it *reflect.MapIter) { // ERROR "leaking param: m$" "it does not escape"
304         mv := reflect.ValueOf(m)
305         it.Reset(mv)
306 }
307
308 func recv1(ch chan string) string { // ERROR "ch does not escape"
309         v := reflect.ValueOf(ch)
310         r, _ := v.Recv()
311         return r.String()
312 }
313
314 func recv2(ch chan string) string { // ERROR "ch does not escape"
315         v := reflect.ValueOf(ch)
316         r, _ := v.TryRecv()
317         return r.String()
318 }
319
320 // Unfortunate: x (the interface storage) doesn't need to escape.
321 func send1(ch chan string, x string) { // ERROR "ch does not escape" "leaking param: x$"
322         vc := reflect.ValueOf(ch)
323         vx := reflect.ValueOf(x) // ERROR "x escapes to heap"
324         vc.Send(vx)
325 }
326
327 // Unfortunate: x (the interface storage) doesn't need to escape.
328 func send2(ch chan string, x string) bool { // ERROR "ch does not escape" "leaking param: x$"
329         vc := reflect.ValueOf(ch)
330         vx := reflect.ValueOf(x) // ERROR "x escapes to heap"
331         return vc.TrySend(vx)
332 }
333
334 func close1(ch chan string) { // ERROR "ch does not escape"
335         v := reflect.ValueOf(ch)
336         v.Close()
337 }
338
339 func select1(ch chan string) string { // ERROR "leaking param: ch$"
340         v := reflect.ValueOf(ch)
341         cas := reflect.SelectCase{Dir: reflect.SelectRecv, Chan: v}
342         _, r, _ := reflect.Select([]reflect.SelectCase{cas}) // ERROR "\[\]reflect.SelectCase{...} does not escape"
343         return r.String()
344 }
345
346 // Unfortunate: x (the interface storage) doesn't need to escape.
347 func select2(ch chan string, x string) { // ERROR "leaking param: ch$" "leaking param: x$"
348         vc := reflect.ValueOf(ch)
349         vx := reflect.ValueOf(x) // ERROR "x escapes to heap"
350         cas := reflect.SelectCase{Dir: reflect.SelectSend, Chan: vc, Send: vx}
351         reflect.Select([]reflect.SelectCase{cas}) // ERROR "\[\]reflect.SelectCase{...} does not escape"
352 }
353
354 var (
355         intTyp    = reflect.TypeOf(int(0))     // ERROR "0 does not escape"
356         uintTyp   = reflect.TypeOf(uint(0))    // ERROR "uint\(0\) does not escape"
357         stringTyp = reflect.TypeOf(string("")) // ERROR ".. does not escape"
358         bytesTyp  = reflect.TypeOf([]byte{})   // ERROR "\[\]byte{} does not escape"
359 )
360
361 // Unfortunate: should not escape.
362 func convert1(x int) uint {
363         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
364         return uint(v.Convert(uintTyp).Uint())
365 }
366
367 // Unfortunate: should only escape content to result.
368 func convert2(x []byte) string { // ERROR "leaking param: x$"
369         v := reflect.ValueOf(x) // ERROR "x escapes to heap"
370         return v.Convert(stringTyp).String()
371 }
372
373 // Unfortunate: v doesn't need to leak, x (the interface storage) doesn't need to escape.
374 func set1(v reflect.Value, x int) { // ERROR "leaking param: v$"
375         vx := reflect.ValueOf(x) // ERROR "x escapes to heap"
376         v.Set(vx)
377 }
378
379 // Unfortunate: a can be stack allocated, x (the interface storage) doesn't need to escape.
380 func set2(x int) int64 {
381         var a int // ERROR "moved to heap: a"
382         v := reflect.ValueOf(&a).Elem()
383         vx := reflect.ValueOf(x) // ERROR "x escapes to heap"
384         v.Set(vx)
385         return v.Int()
386 }
387
388 func set3(v reflect.Value, x int) { // ERROR "v does not escape"
389         v.SetInt(int64(x))
390 }
391
392 func set4(x int) int {
393         var a int
394         v := reflect.ValueOf(&a).Elem() // a should not escape, no error printed
395         v.SetInt(int64(x))
396         return int(v.Int())
397 }
398
399 func set5(v reflect.Value, x string) { // ERROR "v does not escape" "leaking param: x$"
400         v.SetString(x)
401 }
402
403 func set6(v reflect.Value, x []byte) { // ERROR "v does not escape" "leaking param: x$"
404         v.SetBytes(x)
405 }
406
407 func set7(v reflect.Value, x unsafe.Pointer) { // ERROR "v does not escape" "leaking param: x$"
408         v.SetPointer(x)
409 }
410
411 func setmapindex(m map[string]string, k, e string) { // ERROR "m does not escape" "leaking param: k$" "leaking param: e$"
412         mv := reflect.ValueOf(m)
413         kv := reflect.ValueOf(k) // ERROR "k escapes to heap"
414         ev := reflect.ValueOf(e) // ERROR "e escapes to heap"
415         mv.SetMapIndex(kv, ev)
416 }
417
418 // Unfortunate: k doesn't need to escape.
419 func mapdelete(m map[string]string, k string) { // ERROR "m does not escape" "leaking param: k$"
420         mv := reflect.ValueOf(m)
421         kv := reflect.ValueOf(k) // ERROR "k escapes to heap"
422         mv.SetMapIndex(kv, reflect.Value{})
423 }
424
425 // Unfortunate: v doesn't need to leak.
426 func setiterkey1(v reflect.Value, it *reflect.MapIter) { // ERROR "leaking param: v$" "it does not escape"
427         v.SetIterKey(it)
428 }
429
430 // Unfortunate: v doesn't need to leak.
431 func setiterkey2(v reflect.Value, m map[string]string) { // ERROR "leaking param: v$" "leaking param: m$"
432         it := reflect.ValueOf(m).MapRange()
433         v.SetIterKey(it)
434 }
435
436 // Unfortunate: v doesn't need to leak.
437 func setitervalue1(v reflect.Value, it *reflect.MapIter) { // ERROR "leaking param: v$" "it does not escape"
438         v.SetIterValue(it)
439 }
440
441 // Unfortunate: v doesn't need to leak.
442 func setitervalue2(v reflect.Value, m map[string]string) { // ERROR "leaking param: v$" "leaking param: m$"
443         it := reflect.ValueOf(m).MapRange()
444         v.SetIterValue(it)
445 }
446
447 // Unfortunate: s doesn't need escape, only leak to result.
448 // And x (interface storage) doesn't need to escape.
449 func append1(s []int, x int) []int { // ERROR "leaking param: s$"
450         sv := reflect.ValueOf(s)     // ERROR "s escapes to heap"
451         xv := reflect.ValueOf(x)     // ERROR "x escapes to heap"
452         rv := reflect.Append(sv, xv) // ERROR "... argument does not escape"
453         return rv.Interface().([]int)
454 }
455
456 // Unfortunate: s doesn't need escape, only leak to result.
457 func append2(s, x []int) []int { // ERROR "leaking param: s$" "x does not escape"
458         sv := reflect.ValueOf(s) // ERROR "s escapes to heap"
459         xv := reflect.ValueOf(x) // ERROR "x does not escape"
460         rv := reflect.AppendSlice(sv, xv)
461         return rv.Interface().([]int)
462 }