]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape5.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[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 "runtime"
13
14 func noleak(p *int) int { // ERROR "p does not escape"
15         return *p
16 }
17
18 func leaktoret(p *int) *int { // ERROR "leaking param: p to result"
19         return p
20 }
21
22 func leaktoret2(p *int) (*int, *int) { // ERROR "leaking param: p to result ~r1" "leaking param: p to result ~r2"
23         return p, p
24 }
25
26 func leaktoret22(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r2" "leaking param: q to result ~r3"
27         return p, q
28 }
29
30 func leaktoret22b(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
31         return leaktoret22(q, p)
32 }
33
34 func leaktoret22c(p, q *int) (*int, *int) { // ERROR "leaking param: p to result ~r3" "leaking param: q to result ~r2"
35         r, s := leaktoret22(q, p)
36         return r, s
37 }
38
39 func leaktoret22d(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
40         r, s = leaktoret22(q, p)
41         return
42 }
43
44 func leaktoret22e(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
45         r, s = leaktoret22(q, p)
46         return r, s
47 }
48
49 func leaktoret22f(p, q *int) (r, s *int) { // ERROR "leaking param: p to result s" "leaking param: q to result r"
50         rr, ss := leaktoret22(q, p)
51         return rr, ss
52 }
53
54 var gp *int
55
56 func leaktosink(p *int) *int { // ERROR "leaking param: p"
57         gp = p
58         return p
59 }
60
61 func f1() {
62         var x int
63         p := noleak(&x) // ERROR "&x does not escape"
64         _ = p
65 }
66
67 func f2() {
68         var x int
69         p := leaktoret(&x) // ERROR "&x does not escape"
70         _ = p
71 }
72
73 func f3() {
74         var x int          // ERROR "moved to heap: x"
75         p := leaktoret(&x) // ERROR "&x escapes to heap"
76         gp = p
77 }
78
79 func f4() {
80         var x int              // ERROR "moved to heap: x"
81         p, q := leaktoret2(&x) // ERROR "&x escapes to heap"
82         gp = p
83         gp = q
84 }
85
86 func f5() {
87         var x int
88         leaktoret22(leaktoret2(&x)) // ERROR "&x does not escape"
89 }
90
91 func f6() {
92         var x int                               // ERROR "moved to heap: x"
93         px1, px2 := leaktoret22(leaktoret2(&x)) // ERROR "&x escapes to heap"
94         gp = px1
95         _ = px2
96 }
97
98 type T struct{ x int }
99
100 func (t *T) Foo(u int) (*T, bool) { // ERROR "leaking param: t to result"
101         t.x += u
102         return t, true
103 }
104
105 func f7() *T {
106         r, _ := new(T).Foo(42) // ERROR "new.T. escapes to heap"
107         return r
108 }
109
110 func leakrecursive1(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
111         return leakrecursive2(q, p)
112 }
113
114 func leakrecursive2(p, q *int) (*int, *int) { // ERROR "leaking param: p" "leaking param: q"
115         if *p > *q {
116                 return leakrecursive1(q, p)
117         }
118         // without this, leakrecursive? are safe for p and q, b/c in fact their graph does not have leaking edges.
119         return p, q
120 }
121
122 var global interface{}
123
124 type T1 struct {
125         X *int
126 }
127
128 type T2 struct {
129         Y *T1
130 }
131
132 func f8(p *T1) (k T2) { // ERROR "leaking param: p to result k" "leaking param: p"
133         if p == nil {
134                 k = T2{}
135                 return
136         }
137
138         // should make p leak always
139         global = p // ERROR "p escapes to heap"
140         return T2{p}
141 }
142
143 func f9() {
144         var j T1 // ERROR "moved to heap: j"
145         f8(&j)   // ERROR "&j escapes to heap"
146 }
147
148 func f10() {
149         // These don't escape but are too big for the stack
150         var x [1 << 30]byte         // ERROR "moved to heap: x"
151         var y = make([]byte, 1<<30) // ERROR "make\(\[\]byte, 1 << 30\) escapes to heap"
152         _ = x[0] + y[0]
153 }
154
155 // Test for issue 19687 (passing to unnamed parameters does not escape).
156 func f11(**int) {
157 }
158 func f12(_ **int) {
159 }
160 func f13() {
161         var x *int
162         f11(&x)               // ERROR "&x does not escape"
163         f12(&x)               // ERROR "&x does not escape"
164         runtime.KeepAlive(&x) // ERROR "&x does not escape"
165 }
166
167 // Test for issue 24305 (passing to unnamed receivers does not escape).
168 type U int
169
170 func (*U) M()   {}
171 func (_ *U) N() {}
172
173 func _() {
174         var u U
175         u.M() // ERROR "u does not escape"
176         u.N() // ERROR "u does not escape"
177 }
178
179 // Issue 24730: taking address in a loop causes unnecessary escape
180 type T24730 struct {
181         x [64]byte
182 }
183
184 func (t *T24730) g() { // ERROR "t does not escape"
185         y := t.x[:]             // ERROR "t\.x does not escape"
186         for i := range t.x[:] { // ERROR "t\.x does not escape"
187                 y = t.x[:] // ERROR "t\.x does not escape"
188                 y[i] = 1
189         }
190
191         var z *byte
192         for i := range t.x[:] { // ERROR "t\.x does not escape"
193                 z = &t.x[i] // ERROR "t\.x\[i\] does not escape"
194                 *z = 2
195         }
196 }
197
198 // Issue 15730: copy causes unnecessary escape
199
200 var sink []byte
201 var sink2 []int
202 var sink3 []*int
203
204 func f15730a(args ...interface{}) { // ERROR "args does not escape"
205         for _, arg := range args {
206                 switch a := arg.(type) {
207                 case string:
208                         copy(sink, a)
209                 }
210         }
211 }
212
213 func f15730b(args ...interface{}) { // ERROR "args does not escape"
214         for _, arg := range args {
215                 switch a := arg.(type) {
216                 case []int:
217                         copy(sink2, a)
218                 }
219         }
220 }
221
222 func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
223         for _, arg := range args {
224                 switch a := arg.(type) {
225                 case []*int:
226                         // copy pointerful data should cause escape
227                         copy(sink3, a)
228                 }
229         }
230 }