]> Cypherpunks.ru repositories - gostls13.git/blob - test/inline.go
[dev.typeparams] all: merge master (798ec73) into dev.typeparams
[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         "runtime"
14         "unsafe"
15 )
16
17 func add2(p *byte, n uintptr) *byte { // ERROR "can inline add2" "leaking param: p to result"
18         return (*byte)(add1(unsafe.Pointer(p), n)) // ERROR "inlining call to add1"
19 }
20
21 func add1(p unsafe.Pointer, x uintptr) unsafe.Pointer { // ERROR "can inline add1" "leaking param: p to result"
22         return unsafe.Pointer(uintptr(p) + x)
23 }
24
25 func f(x *byte) *byte { // ERROR "can inline f" "leaking param: x to result"
26         return add2(x, 1) // ERROR "inlining call to add2" "inlining call to add1"
27 }
28
29 //go:noinline
30 func g(x int) int {
31         return x + 1
32 }
33
34 func h(x int) int { // ERROR "can inline h"
35         return x + 2
36 }
37
38 func i(x int) int { // ERROR "can inline i"
39         const y = 2
40         return x + y
41 }
42
43 func j(x int) int { // ERROR "can inline j"
44         switch {
45         case x > 0:
46                 return x + 2
47         default:
48                 return x + 1
49         }
50 }
51
52 func _() int { // ERROR "can inline _"
53         tmp1 := h
54         tmp2 := tmp1
55         return tmp2(0) // ERROR "inlining call to h"
56 }
57
58 var somethingWrong error
59
60 // local closures can be inlined
61 func l(x, y int) (int, int, error) { // ERROR "can inline l"
62         e := func(err error) (int, int, error) { // ERROR "can inline l.func1" "func literal does not escape" "leaking param: err to result"
63                 return 0, 0, err
64         }
65         if x == y {
66                 e(somethingWrong) // ERROR "inlining call to l.func1"
67         } else {
68                 f := e
69                 f(nil) // ERROR "inlining call to l.func1"
70         }
71         return y, x, nil
72 }
73
74 // any re-assignment prevents closure inlining
75 func m() int {
76         foo := func() int { return 1 } // ERROR "can inline m.func1" "func literal does not escape"
77         x := foo()
78         foo = func() int { return 2 } // ERROR "can inline m.func2" "func literal does not escape"
79         return x + foo()
80 }
81
82 // address taking prevents closure inlining
83 func n() int {
84         foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
85         bar := &foo
86         x := (*bar)() + foo()
87         return x
88 }
89
90 // make sure assignment inside closure is detected
91 func o() int {
92         foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape"
93         func(x int) {                  // ERROR "can inline o.func2"
94                 if x > 10 {
95                         foo = func() int { return 2 } // ERROR "func literal does not escape" "can inline o.func2"
96                 }
97         }(11) // ERROR "inlining call to o.func2"
98         return foo()
99 }
100
101 func p() int { // ERROR "can inline p"
102         return func() int { return 42 }() // ERROR "can inline p.func1" "inlining call to p.func1"
103 }
104
105 func q(x int) int { // ERROR "can inline q"
106         foo := func() int { return x * 2 } // ERROR "can inline q.func1" "func literal does not escape"
107         return foo()                       // ERROR "inlining call to q.func1"
108 }
109
110 func r(z int) int {
111         foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
112                 return x + z
113         }
114         bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2"
115                 return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3"
116                         return 2*y + x*z
117                 }(x) // ERROR "inlining call to r.func2.1"
118         }
119         return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3"
120 }
121
122 func s0(x int) int { // ERROR "can inline s0"
123         foo := func() { // ERROR "can inline s0.func1" "func literal does not escape"
124                 x = x + 1
125         }
126         foo() // ERROR "inlining call to s0.func1"
127         return x
128 }
129
130 func s1(x int) int { // ERROR "can inline s1"
131         foo := func() int { // ERROR "can inline s1.func1" "func literal does not escape"
132                 return x
133         }
134         x = x + 1
135         return foo() // ERROR "inlining call to s1.func1"
136 }
137
138 // can't currently inline functions with a break statement
139 func switchBreak(x, y int) int {
140         var n int
141         switch x {
142         case 0:
143                 n = 1
144         Done:
145                 switch y {
146                 case 0:
147                         n += 10
148                         break Done
149                 }
150                 n = 2
151         }
152         return n
153 }
154
155 func switchType(x interface{}) int { // ERROR "can inline switchType" "x does not escape"
156         switch x.(type) {
157         case int:
158                 return x.(int)
159         default:
160                 return 0
161         }
162 }
163
164 type T struct{}
165
166 func (T) meth(int, int) {} // ERROR "can inline T.meth"
167
168 func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k"
169
170 func _() { // ERROR "can inline _"
171         T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth"
172         // ERRORAUTO "inlining call to T.meth"
173 }
174
175 func small1() { // ERROR "can inline small1"
176         runtime.GC()
177 }
178 func small2() int { // ERROR "can inline small2"
179         return runtime.GOMAXPROCS(0)
180 }
181 func small3(t T) { // ERROR "can inline small3"
182         t.meth2(3, 5)
183 }
184 func small4(t T) { // not inlineable - has 2 calls.
185         t.meth2(runtime.GOMAXPROCS(0), 5)
186 }
187 func (T) meth2(int, int) { // not inlineable - has 2 calls.
188         runtime.GC()
189         runtime.GC()
190 }
191
192 // Issue #29737 - make sure we can do inlining for a chain of recursive functions
193 func ee() { // ERROR "can inline ee"
194         ff(100) // ERROR "inlining call to ff" "inlining call to gg" "inlining call to hh"
195 }
196
197 func ff(x int) { // ERROR "can inline ff"
198         if x < 0 {
199                 return
200         }
201         gg(x - 1)
202 }
203 func gg(x int) { // ERROR "can inline gg"
204         hh(x - 1)
205 }
206 func hh(x int) { // ERROR "can inline hh"
207         ff(x - 1) // ERROR "inlining call to ff"  // ERROR "inlining call to gg"
208 }
209
210 // Issue #14768 - make sure we can inline for loops.
211 func for1(fn func() bool) { // ERROR "can inline for1" "fn does not escape"
212         for {
213                 if fn() {
214                         break
215                 } else {
216                         continue
217                 }
218         }
219 }
220
221 // BAD: for2 should be inlineable too.
222 func for2(fn func() bool) { // ERROR "fn does not escape"
223 Loop:
224         for {
225                 if fn() {
226                         break Loop
227                 } else {
228                         continue Loop
229                 }
230         }
231 }
232
233 // Issue #18493 - make sure we can do inlining of functions with a method value
234 type T1 struct{}
235
236 func (a T1) meth(val int) int { // ERROR "can inline T1.meth"
237         return val + 5
238 }
239
240 func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth"
241         return t1.meth // ERROR "t1.meth escapes to heap"
242         // ERRORAUTO "inlining call to T1.meth"
243 }
244
245 func ii() { // ERROR "can inline ii"
246         var t1 T1
247         f := getMeth(t1) // ERROR "inlining call to getMeth" "t1.meth does not escape"
248         _ = f(3)
249 }
250
251 // Issue #42194 - make sure that functions evaluated in
252 // go and defer statements can be inlined.
253 func gd1(int) {
254         defer gd1(gd2()) // ERROR "inlining call to gd2"
255         defer gd3()()    // ERROR "inlining call to gd3"
256         go gd1(gd2())    // ERROR "inlining call to gd2"
257         go gd3()()       // ERROR "inlining call to gd3"
258 }
259
260 func gd2() int { // ERROR "can inline gd2"
261         return 1
262 }
263
264 func gd3() func() { // ERROR "can inline gd3"
265         return ii
266 }
267
268 // Issue #42788 - ensure ODEREF OCONVNOP* OADDR is low cost.
269 func EncodeQuad(d []uint32, x [6]float32) { // ERROR "can inline EncodeQuad" "d does not escape"
270         _ = d[:6]
271         d[0] = float32bits(x[0]) // ERROR "inlining call to float32bits"
272         d[1] = float32bits(x[1]) // ERROR "inlining call to float32bits"
273         d[2] = float32bits(x[2]) // ERROR "inlining call to float32bits"
274         d[3] = float32bits(x[3]) // ERROR "inlining call to float32bits"
275         d[4] = float32bits(x[4]) // ERROR "inlining call to float32bits"
276         d[5] = float32bits(x[5]) // ERROR "inlining call to float32bits"
277 }
278
279 // float32bits is a copy of math.Float32bits to ensure that
280 // these tests pass with `-gcflags=-l`.
281 func float32bits(f float32) uint32 { // ERROR "can inline float32bits"
282         return *(*uint32)(unsafe.Pointer(&f))
283 }
284
285 // Ensure OCONVNOP is zero cost.
286 func Conv(v uint64) uint64 { // ERROR "can inline Conv"
287         return conv2(conv2(conv2(v))) // ERROR "inlining call to (conv1|conv2)"
288 }
289 func conv2(v uint64) uint64 { // ERROR "can inline conv2"
290         return conv1(conv1(conv1(conv1(v)))) // ERROR "inlining call to conv1"
291 }
292 func conv1(v uint64) uint64 { // ERROR "can inline conv1"
293         return uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(uint64(v)))))))))))
294 }