]> Cypherpunks.ru repositories - gostls13.git/blob - test/inline.go
test: add test cases for index value with range array clear
[gostls13.git] / test / inline.go
1 // errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
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, using compiler diagnostic flags, that inlining is working.
8 // Compiles but does not run.
9
10 package foo
11
12 import (
13         "errors"
14         "runtime"
15         "unsafe"
16 )
17
18 func add2(p *byte, n uintptr) *byte { // ERROR "can inline add2" "leaking param: p to result"
19         return (*byte)(add1(unsafe.Pointer(p), n)) // ERROR "inlining call to add1"
20 }
21
22 func add1(p unsafe.Pointer, x uintptr) unsafe.Pointer { // ERROR "can inline add1" "leaking param: p to result"
23         return unsafe.Pointer(uintptr(p) + x)
24 }
25
26 func f(x *byte) *byte { // ERROR "can inline f" "leaking param: x to result"
27         return add2(x, 1) // ERROR "inlining call to add2" "inlining call to add1"
28 }
29
30 //go:noinline
31 func g(x int) int {
32         return x + 1
33 }
34
35 func h(x int) int { // ERROR "can inline h"
36         return x + 2
37 }
38
39 func i(x int) int { // ERROR "can inline i"
40         const y = 2
41         return x + y
42 }
43
44 func j(x int) int { // ERROR "can inline j"
45         switch {
46         case x > 0:
47                 return x + 2
48         default:
49                 return x + 1
50         }
51 }
52
53 func f2() int { // ERROR "can inline f2"
54         tmp1 := h
55         tmp2 := tmp1
56         return tmp2(0) // ERROR "inlining call to h"
57 }
58
59 var abc = errors.New("abc") // ERROR "inlining call to errors.New"
60
61 var somethingWrong error
62
63 // local closures can be inlined
64 func l(x, y int) (int, int, error) { // ERROR "can inline l"
65         e := func(err error) (int, int, error) { // ERROR "can inline l.func1" "func literal does not escape" "leaking param: err to result"
66                 return 0, 0, err
67         }
68         if x == y {
69                 e(somethingWrong) // ERROR "inlining call to l.func1"
70         } else {
71                 f := e
72                 f(nil) // ERROR "inlining call to l.func1"
73         }
74         return y, x, nil
75 }
76
77 // any re-assignment prevents closure inlining
78 func m() int {
79         foo := func() int { return 1 } // ERROR "can inline m.func1" "func literal does not escape"
80         x := foo()
81         foo = func() int { return 2 } // ERROR "can inline m.func2" "func literal does not escape"
82         return x + foo()
83 }
84
85 // address taking prevents closure inlining
86 func n() int {
87         foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
88         bar := &foo
89         x := (*bar)() + foo()
90         return x
91 }
92
93 // make sure assignment inside closure is detected
94 func o() int {
95         foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape"
96         func(x int) {                  // ERROR "can inline o.func2"
97                 if x > 10 {
98                         foo = func() int { return 2 } // ERROR "can inline o.func2"
99                 }
100         }(11) // ERROR "func literal does not escape" "inlining call to o.func2"
101         return foo()
102 }
103
104 func p() int { // ERROR "can inline p"
105         return func() int { return 42 }() // ERROR "can inline p.func1" "inlining call to p.func1"
106 }
107
108 func q(x int) int { // ERROR "can inline q"
109         foo := func() int { return x * 2 } // ERROR "can inline q.func1" "func literal does not escape"
110         return foo()                       // ERROR "inlining call to q.func1"
111 }
112
113 func r(z int) int {
114         foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
115                 return x + z
116         }
117         bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2"
118                 return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.r.func2.func3"
119                         return 2*y + x*z
120                 }(x) // ERROR "inlining call to r.func2.1"
121         }
122         return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.r.func2.func3"
123 }
124
125 func s0(x int) int { // ERROR "can inline s0"
126         foo := func() { // ERROR "can inline s0.func1" "func literal does not escape"
127                 x = x + 1
128         }
129         foo() // ERROR "inlining call to s0.func1"
130         return x
131 }
132
133 func s1(x int) int { // ERROR "can inline s1"
134         foo := func() int { // ERROR "can inline s1.func1" "func literal does not escape"
135                 return x
136         }
137         x = x + 1
138         return foo() // ERROR "inlining call to s1.func1"
139 }
140
141 func switchBreak(x, y int) int { // ERROR "can inline switchBreak"
142         var n int
143         switch x {
144         case 0:
145                 n = 1
146         Done:
147                 switch y {
148                 case 0:
149                         n += 10
150                         break Done
151                 }
152                 n = 2
153         }
154         return n
155 }
156
157 func switchType(x interface{}) int { // ERROR "can inline switchType" "x does not escape"
158         switch x.(type) {
159         case int:
160                 return x.(int)
161         default:
162                 return 0
163         }
164 }
165
166 // Test that switches on constant things, with constant cases, only cost anything for
167 // the case that matches. See issue 50253.
168 func switchConst1(p func(string)) { // ERROR "can inline switchConst" "p does not escape"
169         const c = 1
170         switch c {
171         case 0:
172                 p("zero")
173         case 1:
174                 p("one")
175         case 2:
176                 p("two")
177         default:
178                 p("other")
179         }
180 }
181
182 func switchConst2() string { // ERROR "can inline switchConst2"
183         switch runtime.GOOS {
184         case "linux":
185                 return "Leenooks"
186         case "windows":
187                 return "Windoze"
188         case "darwin":
189                 return "MackBone"
190         case "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100":
191                 return "Numbers"
192         default:
193                 return "oh nose!"
194         }
195 }
196 func switchConst3() string { // ERROR "can inline switchConst3"
197         switch runtime.GOOS {
198         case "Linux":
199                 panic("Linux")
200         case "Windows":
201                 panic("Windows")
202         case "Darwin":
203                 panic("Darwin")
204         case "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100":
205                 panic("Numbers")
206         default:
207                 return "oh nose!"
208         }
209 }
210 func switchConst4() { // ERROR "can inline switchConst4"
211         const intSize = 32 << (^uint(0) >> 63)
212         want := func() string { // ERROR "can inline switchConst4.func1"
213                 switch intSize {
214                 case 32:
215                         return "32"
216                 case 64:
217                         return "64"
218                 default:
219                         panic("unreachable")
220                 }
221         }() // ERROR "inlining call to switchConst4.func1"
222         _ = want
223 }
224
225 func inlineRangeIntoMe(data []int) { // ERROR "can inline inlineRangeIntoMe" "data does not escape"
226         rangeFunc(data, 12) // ERROR "inlining call to rangeFunc"
227 }
228
229 func rangeFunc(xs []int, b int) int { // ERROR "can inline rangeFunc" "xs does not escape"
230         for i, x := range xs {
231                 if x == b {
232                         return i
233                 }
234         }
235         return -1
236 }
237
238 type T struct{}
239
240 func (T) meth(int, int) {} // ERROR "can inline T.meth"
241
242 func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k"
243
244 func f3() { // ERROR "can inline f3"
245         T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth"
246         // ERRORAUTO "inlining call to T.meth"
247 }
248
249 func small1() { // ERROR "can inline small1"
250         runtime.GC()
251 }
252 func small2() int { // ERROR "can inline small2"
253         return runtime.GOMAXPROCS(0)
254 }
255 func small3(t T) { // ERROR "can inline small3"
256         t.meth2(3, 5)
257 }
258 func small4(t T) { // not inlineable - has 2 calls.
259         t.meth2(runtime.GOMAXPROCS(0), 5)
260 }
261 func (T) meth2(int, int) { // not inlineable - has 2 calls.
262         runtime.GC()
263         runtime.GC()
264 }
265
266 // Issue #29737 - make sure we can do inlining for a chain of recursive functions
267 func ee() { // ERROR "can inline ee"
268         ff(100) // ERROR "inlining call to ff" "inlining call to gg" "inlining call to hh"
269 }
270
271 func ff(x int) { // ERROR "can inline ff"
272         if x < 0 {
273                 return
274         }
275         gg(x - 1) // ERROR "inlining call to gg" "inlining call to hh"
276 }
277 func gg(x int) { // ERROR "can inline gg"
278         hh(x - 1) // ERROR "inlining call to hh" "inlining call to ff"
279 }
280 func hh(x int) { // ERROR "can inline hh"
281         ff(x - 1) // ERROR "inlining call to ff" "inlining call to gg"
282 }
283
284 // Issue #14768 - make sure we can inline for loops.
285 func for1(fn func() bool) { // ERROR "can inline for1" "fn does not escape"
286         for {
287                 if fn() {
288                         break
289                 } else {
290                         continue
291                 }
292         }
293 }
294
295 func for2(fn func() bool) { // ERROR "can inline for2" "fn does not escape"
296 Loop:
297         for {
298                 if fn() {
299                         break Loop
300                 } else {
301                         continue Loop
302                 }
303         }
304 }
305
306 // Issue #18493 - make sure we can do inlining of functions with a method value
307 type T1 struct{}
308
309 func (a T1) meth(val int) int { // ERROR "can inline T1.meth"
310         return val + 5
311 }
312
313 func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth"
314         return t1.meth // ERROR "t1.meth escapes to heap"
315         // ERRORAUTO "inlining call to T1.meth"
316 }
317
318 func ii() { // ERROR "can inline ii"
319         var t1 T1
320         f := getMeth(t1) // ERROR "inlining call to getMeth" "t1.meth does not escape"
321         _ = f(3)
322 }
323
324 // Issue #42194 - make sure that functions evaluated in
325 // go and defer statements can be inlined.
326 func gd1(int) {
327         defer gd1(gd2()) // ERROR "inlining call to gd2"
328         defer gd3()()    // ERROR "inlining call to gd3"
329         go gd1(gd2())    // ERROR "inlining call to gd2"
330         go gd3()()       // ERROR "inlining call to gd3"
331 }
332
333 func gd2() int { // ERROR "can inline gd2"
334         return 1
335 }
336
337 func gd3() func() { // ERROR "can inline gd3"
338         return ii
339 }
340
341 // Issue #42788 - ensure ODEREF OCONVNOP* OADDR is low cost.
342 func EncodeQuad(d []uint32, x [6]float32) { // ERROR "can inline EncodeQuad" "d does not escape"
343         _ = d[:6]
344         d[0] = float32bits(x[0]) // ERROR "inlining call to float32bits"
345         d[1] = float32bits(x[1]) // ERROR "inlining call to float32bits"
346         d[2] = float32bits(x[2]) // ERROR "inlining call to float32bits"
347         d[3] = float32bits(x[3]) // ERROR "inlining call to float32bits"
348         d[4] = float32bits(x[4]) // ERROR "inlining call to float32bits"
349         d[5] = float32bits(x[5]) // ERROR "inlining call to float32bits"
350 }
351
352 // float32bits is a copy of math.Float32bits to ensure that
353 // these tests pass with `-gcflags=-l`.
354 func float32bits(f float32) uint32 { // ERROR "can inline float32bits"
355         return *(*uint32)(unsafe.Pointer(&f))
356 }
357
358 // Ensure OCONVNOP is zero cost.
359 func Conv(v uint64) uint64 { // ERROR "can inline Conv"
360         return conv2(conv2(conv2(v))) // ERROR "inlining call to (conv1|conv2)"
361 }
362 func conv2(v uint64) uint64 { // ERROR "can inline conv2"
363         return conv1(conv1(conv1(conv1(v)))) // ERROR "inlining call to conv1"
364 }
365 func conv1(v uint64) uint64 { // ERROR "can inline conv1"
366         return uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(v)))))))))))
367 }
368
369 func select1(x, y chan bool) int { // ERROR "can inline select1" "x does not escape" "y does not escape"
370         select {
371         case <-x:
372                 return 1
373         case <-y:
374                 return 2
375         }
376 }
377
378 func select2(x, y chan bool) { // ERROR "can inline select2" "x does not escape" "y does not escape"
379 loop: // test that labeled select can be inlined.
380         select {
381         case <-x:
382                 break loop
383         case <-y:
384         }
385 }
386
387 func inlineSelect2(x, y chan bool) { // ERROR "can inline inlineSelect2" ERROR "x does not escape" "y does not escape"
388 loop:
389         for i := 0; i < 5; i++ {
390                 if i == 3 {
391                         break loop
392                 }
393                 select2(x, y) // ERROR "inlining call to select2"
394         }
395 }