]> Cypherpunks.ru repositories - gostls13.git/blob - test/escape_struct_param2.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / escape_struct_param2.go
1 // errorcheck -0 -m -l
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 escape analysis for struct function parameters.
8 // Note companion strict_param1 checks *struct function parameters with similar tests.
9
10 package notmain
11
12 var Ssink *string
13
14 type U struct {
15         _sp  *string
16         _spp **string
17 }
18
19 type V struct {
20         _u   U
21         _up  *U
22         _upp **U
23 }
24
25 func (u U) SP() *string { // ERROR "leaking param: u to result ~r0 level=0$"
26         return u._sp
27 }
28
29 func (u U) SPP() **string { // ERROR "leaking param: u to result ~r0 level=0$"
30         return u._spp
31 }
32
33 func (u U) SPPi() *string { // ERROR "leaking param: u to result ~r0 level=1$"
34         return *u._spp
35 }
36
37 func tSPPi() {
38         s := "cat" // ERROR "moved to heap: s$"
39         ps := &s
40         pps := &ps
41         pu := &U{ps, pps} // ERROR "&U{...} does not escape$"
42         Ssink = pu.SPPi()
43 }
44
45 func tiSPP() {
46         s := "cat" // ERROR "moved to heap: s$"
47         ps := &s
48         pps := &ps
49         pu := &U{ps, pps} // ERROR "&U{...} does not escape$"
50         Ssink = *pu.SPP()
51 }
52
53 // BAD: need fine-grained analysis to avoid spurious escape of ps
54 func tSP() {
55         s := "cat" // ERROR "moved to heap: s$"
56         ps := &s   // ERROR "moved to heap: ps$"
57         pps := &ps
58         pu := &U{ps, pps} // ERROR "&U{...} does not escape$"
59         Ssink = pu.SP()
60 }
61
62 func (v V) u() U { // ERROR "leaking param: v to result ~r0 level=0$"
63         return v._u
64 }
65
66 func (v V) UP() *U { // ERROR "leaking param: v to result ~r0 level=0$"
67         return v._up
68 }
69
70 func (v V) UPP() **U { // ERROR "leaking param: v to result ~r0 level=0$"
71         return v._upp
72 }
73
74 func (v V) UPPia() *U { // ERROR "leaking param: v to result ~r0 level=1$"
75         return *v._upp
76 }
77
78 func (v V) UPPib() *U { // ERROR "leaking param: v to result ~r0 level=1$"
79         return *v.UPP()
80 }
81
82 func (v V) USPa() *string { // ERROR "leaking param: v to result ~r0 level=0$"
83         return v._u._sp
84 }
85
86 func (v V) USPb() *string { // ERROR "leaking param: v to result ~r0 level=0$"
87         return v.u()._sp
88 }
89
90 func (v V) USPPia() *string { // ERROR "leaking param: v to result ~r0 level=1$"
91         return *v._u._spp
92 }
93
94 func (v V) USPPib() *string { // ERROR "leaking param: v to result ~r0 level=1$"
95         return v._u.SPPi()
96 }
97
98 func (v V) UPiSPa() *string { // ERROR "leaking param: v to result ~r0 level=1$"
99         return v._up._sp
100 }
101
102 func (v V) UPiSPb() *string { // ERROR "leaking param: v to result ~r0 level=1$"
103         return v._up.SP()
104 }
105
106 func (v V) UPiSPc() *string { // ERROR "leaking param: v to result ~r0 level=1$"
107         return v.UP()._sp
108 }
109
110 func (v V) UPiSPd() *string { // ERROR "leaking param: v to result ~r0 level=1$"
111         return v.UP().SP()
112 }
113
114 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3
115 func tUPiSPa() {
116         s1 := "ant"
117         s2 := "bat" // ERROR "moved to heap: s2$"
118         s3 := "cat" // ERROR "moved to heap: s3$"
119         s4 := "dog" // ERROR "moved to heap: s4$"
120         s5 := "emu" // ERROR "moved to heap: s5$"
121         s6 := "fox" // ERROR "moved to heap: s6$"
122         ps2 := &s2
123         ps4 := &s4 // ERROR "moved to heap: ps4$"
124         ps6 := &s6 // ERROR "moved to heap: ps6$"
125         u1 := U{&s1, &ps2}
126         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
127         u3 := &U{&s5, &ps6}  // ERROR "&U{...} escapes to heap$"
128         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
129         Ssink = v.UPiSPa()   // Ssink = &s3 (only &s3 really escapes)
130 }
131
132 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3
133 func tUPiSPb() {
134         s1 := "ant"
135         s2 := "bat" // ERROR "moved to heap: s2$"
136         s3 := "cat" // ERROR "moved to heap: s3$"
137         s4 := "dog" // ERROR "moved to heap: s4$"
138         s5 := "emu" // ERROR "moved to heap: s5$"
139         s6 := "fox" // ERROR "moved to heap: s6$"
140         ps2 := &s2
141         ps4 := &s4 // ERROR "moved to heap: ps4$"
142         ps6 := &s6 // ERROR "moved to heap: ps6$"
143         u1 := U{&s1, &ps2}
144         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
145         u3 := &U{&s5, &ps6}  // ERROR "&U{...} escapes to heap$"
146         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
147         Ssink = v.UPiSPb()   // Ssink = &s3 (only &s3 really escapes)
148 }
149
150 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3
151 func tUPiSPc() {
152         s1 := "ant"
153         s2 := "bat" // ERROR "moved to heap: s2$"
154         s3 := "cat" // ERROR "moved to heap: s3$"
155         s4 := "dog" // ERROR "moved to heap: s4$"
156         s5 := "emu" // ERROR "moved to heap: s5$"
157         s6 := "fox" // ERROR "moved to heap: s6$"
158         ps2 := &s2
159         ps4 := &s4 // ERROR "moved to heap: ps4$"
160         ps6 := &s6 // ERROR "moved to heap: ps6$"
161         u1 := U{&s1, &ps2}
162         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
163         u3 := &U{&s5, &ps6}  // ERROR "&U{...} escapes to heap$"
164         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
165         Ssink = v.UPiSPc()   // Ssink = &s3 (only &s3 really escapes)
166 }
167
168 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s3
169 func tUPiSPd() {
170         s1 := "ant"
171         s2 := "bat" // ERROR "moved to heap: s2$"
172         s3 := "cat" // ERROR "moved to heap: s3$"
173         s4 := "dog" // ERROR "moved to heap: s4$"
174         s5 := "emu" // ERROR "moved to heap: s5$"
175         s6 := "fox" // ERROR "moved to heap: s6$"
176         ps2 := &s2
177         ps4 := &s4 // ERROR "moved to heap: ps4$"
178         ps6 := &s6 // ERROR "moved to heap: ps6$"
179         u1 := U{&s1, &ps2}
180         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
181         u3 := &U{&s5, &ps6}  // ERROR "&U{...} escapes to heap$"
182         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
183         Ssink = v.UPiSPd()   // Ssink = &s3 (only &s3 really escapes)
184 }
185
186 func (v V) UPiSPPia() *string { // ERROR "leaking param: v to result ~r0 level=2$"
187         return *v._up._spp
188 }
189
190 func (v V) UPiSPPib() *string { // ERROR "leaking param: v to result ~r0 level=2$"
191         return v._up.SPPi()
192 }
193
194 func (v V) UPiSPPic() *string { // ERROR "leaking param: v to result ~r0 level=2$"
195         return *v.UP()._spp
196 }
197
198 func (v V) UPiSPPid() *string { // ERROR "leaking param: v to result ~r0 level=2$"
199         return v.UP().SPPi()
200 }
201
202 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s4
203 func tUPiSPPia() {
204         s1 := "ant"
205         s2 := "bat"
206         s3 := "cat"
207         s4 := "dog" // ERROR "moved to heap: s4$"
208         s5 := "emu" // ERROR "moved to heap: s5$"
209         s6 := "fox" // ERROR "moved to heap: s6$"
210         ps2 := &s2
211         ps4 := &s4
212         ps6 := &s6 // ERROR "moved to heap: ps6$"
213         u1 := U{&s1, &ps2}
214         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
215         u3 := &U{&s5, &ps6}  // ERROR "&U{...} does not escape$"
216         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
217         Ssink = v.UPiSPPia() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
218 }
219
220 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s4
221 func tUPiSPPib() {
222         s1 := "ant"
223         s2 := "bat"
224         s3 := "cat"
225         s4 := "dog" // ERROR "moved to heap: s4$"
226         s5 := "emu" // ERROR "moved to heap: s5$"
227         s6 := "fox" // ERROR "moved to heap: s6$"
228         ps2 := &s2
229         ps4 := &s4
230         ps6 := &s6 // ERROR "moved to heap: ps6$"
231         u1 := U{&s1, &ps2}
232         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
233         u3 := &U{&s5, &ps6}  // ERROR "&U{...} does not escape$"
234         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
235         Ssink = v.UPiSPPib() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
236 }
237
238 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s4
239 func tUPiSPPic() {
240         s1 := "ant"
241         s2 := "bat"
242         s3 := "cat"
243         s4 := "dog" // ERROR "moved to heap: s4$"
244         s5 := "emu" // ERROR "moved to heap: s5$"
245         s6 := "fox" // ERROR "moved to heap: s6$"
246         ps2 := &s2
247         ps4 := &s4
248         ps6 := &s6 // ERROR "moved to heap: ps6$"
249         u1 := U{&s1, &ps2}
250         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
251         u3 := &U{&s5, &ps6}  // ERROR "&U{...} does not escape$"
252         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
253         Ssink = v.UPiSPPic() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
254 }
255
256 // BAD: need fine-grained (field-sensitive) analysis to avoid spurious escape of all but &s4
257 func tUPiSPPid() {
258         s1 := "ant"
259         s2 := "bat"
260         s3 := "cat"
261         s4 := "dog" // ERROR "moved to heap: s4$"
262         s5 := "emu" // ERROR "moved to heap: s5$"
263         s6 := "fox" // ERROR "moved to heap: s6$"
264         ps2 := &s2
265         ps4 := &s4
266         ps6 := &s6 // ERROR "moved to heap: ps6$"
267         u1 := U{&s1, &ps2}
268         u2 := &U{&s3, &ps4}  // ERROR "&U{...} does not escape$"
269         u3 := &U{&s5, &ps6}  // ERROR "&U{...} does not escape$"
270         v := &V{u1, u2, &u3} // ERROR "&V{...} does not escape$"
271         Ssink = v.UPiSPPid() // Ssink = *&ps4 = &s4 (only &s4 really escapes)
272 }
273
274 func (v V) UPPiSPPia() *string { // ERROR "leaking param: v to result ~r0 level=3$"
275         return *(*v._upp)._spp
276 }
277
278 // This test isolates the one value that needs to escape, not because
279 // it distinguishes fields but because it knows that &s6 is the only
280 // value reachable by two indirects from v.
281 // The test depends on the level cap in the escape analysis tags
282 // being able to encode that fact.
283 func tUPPiSPPia() { // This test is sensitive to the level cap in function summary results.
284         s1 := "ant"
285         s2 := "bat"
286         s3 := "cat"
287         s4 := "dog"
288         s5 := "emu"
289         s6 := "fox" // ERROR "moved to heap: s6$"
290         ps2 := &s2
291         ps4 := &s4
292         ps6 := &s6
293         u1 := U{&s1, &ps2}
294         u2 := &U{&s3, &ps4}   // ERROR "&U{...} does not escape$"
295         u3 := &U{&s5, &ps6}   // ERROR "&U{...} does not escape$"
296         v := &V{u1, u2, &u3}  // ERROR "&V{...} does not escape$"
297         Ssink = v.UPPiSPPia() // Ssink = *&ps6 = &s6 (only &s6 really escapes)
298 }