]> Cypherpunks.ru repositories - gostls13.git/blob - test/inline.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / test / inline.go
1 // errorcheck -0 -m
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 var somethingWrong error = errors.New("something went wrong")
54
55 // local closures can be inlined
56 func l(x, y int) (int, int, error) {
57         e := func(err error) (int, int, error) { // ERROR "can inline l.func1" "func literal does not escape" "leaking param: err to result"
58                 return 0, 0, err
59         }
60         if x == y {
61                 e(somethingWrong) // ERROR "inlining call to l.func1"
62         }
63         return y, x, nil
64 }
65
66 // any re-assignment prevents closure inlining
67 func m() int {
68         foo := func() int { return 1 } // ERROR "can inline m.func1" "func literal does not escape"
69         x := foo()
70         foo = func() int { return 2 } // ERROR "can inline m.func2" "func literal does not escape"
71         return x + foo()
72 }
73
74 // address taking prevents closure inlining
75 func n() int {
76         foo := func() int { return 1 } // ERROR "can inline n.func1" "func literal does not escape"
77         bar := &foo
78         x := (*bar)() + foo()
79         return x
80 }
81
82 // make sure assignment inside closure is detected
83 func o() int {
84         foo := func() int { return 1 } // ERROR "can inline o.func1" "func literal does not escape"
85         func(x int) {                  // ERROR "func literal does not escape"
86                 if x > 10 {
87                         foo = func() int { return 2 } // ERROR "can inline o.func2" "func literal escapes"
88                 }
89         }(11)
90         return foo()
91 }
92
93 func p() int {
94         return func() int { return 42 }() // ERROR "can inline p.func1" "inlining call to p.func1"
95 }
96
97 func q(x int) int {
98         foo := func() int { return x * 2 } // ERROR "can inline q.func1" "func literal does not escape"
99         return foo()                       // ERROR "inlining call to q.func1"
100 }
101
102 func r(z int) int {
103         foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
104                 return x + z
105         }
106         bar := func(x int) int { // ERROR "func literal does not escape"
107                 return x + func(y int) int { // ERROR "can inline r.func2.1"
108                         return 2*y + x*z
109                 }(x) // ERROR "inlining call to r.func2.1"
110         }
111         return foo(42) + bar(42) // ERROR "inlining call to r.func1"
112 }
113
114 func s0(x int) int {
115         foo := func() { // ERROR "can inline s0.func1" "func literal does not escape"
116                 x = x + 1
117         }
118         foo() // ERROR "inlining call to s0.func1"
119         return x
120 }
121
122 func s1(x int) int {
123         foo := func() int { // ERROR "can inline s1.func1" "func literal does not escape"
124                 return x
125         }
126         x = x + 1
127         return foo() // ERROR "inlining call to s1.func1"
128 }
129
130 // can't currently inline functions with a break statement
131 func switchBreak(x, y int) int {
132         var n int
133         switch x {
134         case 0:
135                 n = 1
136         Done:
137                 switch y {
138                 case 0:
139                         n += 10
140                         break Done
141                 }
142                 n = 2
143         }
144         return n
145 }
146
147 // can't currently inline functions with a type switch
148 func switchType(x interface{}) int { // ERROR "x does not escape"
149         switch x.(type) {
150         case int:
151                 return x.(int)
152         default:
153                 return 0
154         }
155 }
156
157 type T struct{}
158
159 func (T) meth(int, int) {} // ERROR "can inline T.meth"
160
161 func k() (T, int, int) { return T{}, 0, 0 } // ERROR "can inline k"
162
163 func _() { // ERROR "can inline _"
164         T.meth(k()) // ERROR "inlining call to k" "inlining call to T.meth"
165 }
166
167 func small1() { // ERROR "can inline small1"
168         runtime.GC()
169 }
170 func small2() int { // ERROR "can inline small2"
171         return runtime.GOMAXPROCS(0)
172 }
173 func small3(t T) { // ERROR "can inline small3"
174         t.meth2(3, 5)
175 }
176 func small4(t T) { // not inlineable - has 2 calls.
177         t.meth2(runtime.GOMAXPROCS(0), 5)
178 }
179 func (T) meth2(int, int) { // not inlineable - has 2 calls.
180         runtime.GC()
181         runtime.GC()
182 }