vxx2 / vlib / v / tests / autofree_labeled_continue_scope_test.v
493 lines · 441 sloc · 8.54 KB · 1a2d0e5b70d6dd1baaa60290f2446e9ece4324bf
Raw
1// vtest build: !sanitize-address-gcc && !sanitize-address-clang
2// vtest vflags: -autofree
3@[has_globals]
4module main
5
6__global (
7 event_code int
8)
9
10type Label = string
11
12struct Tracked {
13 id int
14}
15
16struct Holder {
17 label string
18 other string
19 id int
20}
21
22struct AliasHolder {
23 label Label
24 other string
25 id int
26}
27
28fn (t &Tracked) free() {
29 unsafe {
30 event_code = event_code * 10 + t.id
31 }
32}
33
34fn (h &Holder) free() {
35 push_event(h.id)
36 unsafe {
37 h.label.free()
38 h.other.free()
39 }
40}
41
42fn (h &AliasHolder) free() {
43 push_event(h.id)
44 unsafe {
45 h.label.free()
46 h.other.free()
47 }
48}
49
50fn tracked(id int) Tracked {
51 return Tracked{
52 id: id
53 }
54}
55
56fn holder(id int) Holder {
57 return Holder{
58 label: 'x'.repeat(id)
59 other: 'y'.repeat(id + 1)
60 id: id
61 }
62}
63
64fn alias_holder(id int) AliasHolder {
65 return AliasHolder{
66 label: Label('x'.repeat(id))
67 other: 'y'.repeat(id + 1)
68 id: id
69 }
70}
71
72fn push_event(id int) {
73 unsafe {
74 event_code = event_code * 10 + id
75 }
76}
77
78fn reset_events() {
79 unsafe {
80 event_code = 0
81 }
82}
83
84fn events() int {
85 return unsafe { event_code }
86}
87
88fn labeled_continue_cleanup_order() {
89 outer: for _ in 0 .. 1 {
90 target := tracked(1)
91 if target.id == -1 {
92 push_event(9)
93 }
94 defer {
95 push_event(7 + target.id - 1)
96 }
97 {
98 inner := tracked(2)
99 if inner.id == -1 {
100 push_event(9)
101 }
102 continue outer
103 }
104 after := tracked(3)
105 defer {
106 push_event(8)
107 }
108 if after.id == -1 {
109 push_event(9)
110 }
111 }
112}
113
114fn labeled_fallthrough_cleanup_order() {
115 outer: for _ in 0 .. 1 {
116 target := tracked(1)
117 if target.id == -1 {
118 continue outer
119 }
120 defer {
121 push_event(7 + target.id - 1)
122 }
123 {
124 inner := tracked(2)
125 if inner.id == -1 {
126 continue outer
127 }
128 }
129 }
130}
131
132fn labeled_break_cleanup_order() {
133 break_outer: for _ in 0 .. 1 {
134 target := tracked(1)
135 defer {
136 push_event(7)
137 }
138 {
139 middle := tracked(2)
140 defer {
141 push_event(8)
142 }
143 {
144 inner := tracked(3)
145 defer {
146 push_event(9)
147 }
148 if inner.id == 3 {
149 break break_outer
150 }
151 }
152 }
153 }
154}
155
156fn for_c_all_continue() {
157 mut i := 0
158 outer: for init := tracked(4); i < 2; i++ {
159 if init.id == -1 {
160 push_event(9)
161 }
162 body := tracked(5 + i)
163 if body.id >= 5 {
164 continue outer
165 }
166 }
167}
168
169fn for_c_mixed_fallthrough_continue() {
170 mut i := 0
171 outer: for init := tracked(4); i < 3; i++ {
172 if init.id == -1 {
173 push_event(9)
174 }
175 body := tracked(5 + i)
176 if i == 1 {
177 continue outer
178 }
179 if body.id == -1 {
180 push_event(9)
181 }
182 }
183}
184
185fn for_c_nested_continue_outer_init_cleanup() {
186 mut i := 0
187 outer: for outer_init := tracked(4); i < 2; i++ {
188 if outer_init.id == -1 {
189 push_event(9)
190 }
191 mut j := 0
192 for inner_init := tracked(5); j < 1; j++ {
193 if inner_init.id == -1 {
194 push_event(9)
195 }
196 body := tracked(6)
197 if body.id == 6 {
198 continue outer
199 }
200 }
201 }
202}
203
204fn for_c_nested_break_outer_init_cleanup() {
205 mut i := 0
206 break_outer: for outer_init := tracked(4); i < 1; i++ {
207 if outer_init.id == -1 {
208 push_event(9)
209 }
210 mut j := 0
211 for inner_init := tracked(5); j < 1; j++ {
212 if inner_init.id == -1 {
213 push_event(9)
214 }
215 body := tracked(6)
216 if body.id == 6 {
217 break break_outer
218 }
219 }
220 }
221}
222
223fn for_c_labeled_break() {
224 mut i := 0
225 outer: for init := tracked(4); i < 1; i++ {
226 if init.id == -1 {
227 push_event(9)
228 }
229 body := tracked(5)
230 if body.id == 5 {
231 break outer
232 }
233 }
234}
235
236fn for_c_return() int {
237 mut i := 0
238 for init := tracked(4); i < 1; i++ {
239 if init.id == -1 {
240 push_event(9)
241 }
242 body := tracked(5)
243 if body.id == 5 {
244 return body.id
245 }
246 }
247 return 0
248}
249
250fn for_c_multi_init_return() int {
251 mut i := 0
252 for first, second := tracked(4), tracked(3); i < 1; i++ {
253 if first.id + second.id == -1 {
254 push_event(9)
255 }
256 body := tracked(5)
257 if body.id == 5 {
258 return body.id
259 }
260 }
261 return 0
262}
263
264fn for_c_return_init_string() string {
265 mut i := 0
266 for init := 'ab'.repeat(3); i < 1; i++ {
267 body := tracked(5)
268 if body.id == 5 {
269 return init
270 }
271 }
272 return ''
273}
274
275fn for_c_multi_init_return_second() Tracked {
276 mut i := 0
277 for first, second := tracked(4), tracked(3); i < 1; i++ {
278 if first.id + second.id == -1 {
279 push_event(9)
280 }
281 body := tracked(5)
282 if body.id == 5 {
283 return second
284 }
285 }
286 return tracked(0)
287}
288
289fn for_c_multi_init_return_second_string() string {
290 mut i := 0
291 for first, second := 'x'.repeat(4), 'y'.repeat(3); i < 1; i++ {
292 assert first.len == 4
293 body := tracked(5)
294 if body.id == 5 {
295 return second
296 }
297 }
298 return ''
299}
300
301fn for_c_return_init_field_string() string {
302 mut i := 0
303 for init := holder(4); i < 1; i++ {
304 body := tracked(5)
305 if body.id == 5 {
306 return init.label
307 }
308 }
309 return ''
310}
311
312fn for_c_return_init_field_alias_string() Label {
313 mut i := 0
314 for init := alias_holder(4); i < 1; i++ {
315 body := tracked(5)
316 if body.id == 5 {
317 return init.label
318 }
319 }
320 return Label('')
321}
322
323fn for_c_return_init_field_id() int {
324 mut i := 0
325 for init := holder(4); i < 1; i++ {
326 body := tracked(5)
327 if body.id == 5 {
328 return init.id
329 }
330 }
331 return 0
332}
333
334fn for_c_branch_return_body_after_init_path(cond bool) Tracked {
335 mut i := 0
336 for init := tracked(4); i < 1; i++ {
337 if cond {
338 return init
339 }
340 body := tracked(5)
341 return body
342 }
343 return tracked(0)
344}
345
346fn for_c_multi_init_branch_return_body_after_second_path(cond bool) Tracked {
347 mut i := 0
348 for first, second := tracked(4), tracked(3); i < 1; i++ {
349 if cond {
350 return second
351 }
352 body := tracked(5)
353 return body
354 }
355 return tracked(0)
356}
357
358fn for_c_branch_return_body_after_init_string_path(cond bool) string {
359 mut i := 0
360 for init := 'z'.repeat(4); i < 1; i++ {
361 if cond {
362 return init
363 }
364 body := tracked(5)
365 if body.id == 5 {
366 return 'body'
367 }
368 }
369 return ''
370}
371
372fn test_labeled_continue_runs_reached_target_defer_before_target_autofree() {
373 reset_events()
374 labeled_continue_cleanup_order()
375 assert events() == 271
376}
377
378fn test_labeled_fallthrough_runs_target_defer_before_target_autofree() {
379 reset_events()
380 labeled_fallthrough_cleanup_order()
381 assert events() == 271
382}
383
384fn test_labeled_break_runs_all_exited_defers_before_jump() {
385 reset_events()
386 labeled_break_cleanup_order()
387 assert events() == 938271
388}
389
390fn test_for_c_all_continue_frees_init_once_after_loop() {
391 reset_events()
392 for_c_all_continue()
393 assert events() == 564
394}
395
396fn test_for_c_mixed_fallthrough_continue_keeps_init_until_loop_exit() {
397 reset_events()
398 for_c_mixed_fallthrough_continue()
399 assert events() == 5674
400}
401
402fn test_for_c_nested_continue_outer_frees_inner_init_before_jump() {
403 reset_events()
404 for_c_nested_continue_outer_init_cleanup()
405 assert events() == 65654
406}
407
408fn test_for_c_nested_break_outer_frees_inner_init_before_jump() {
409 reset_events()
410 for_c_nested_break_outer_init_cleanup()
411 assert events() == 654
412}
413
414fn test_for_c_labeled_break_frees_init_once_after_body() {
415 reset_events()
416 for_c_labeled_break()
417 assert events() == 54
418}
419
420fn test_for_c_return_frees_init_once_after_body() {
421 reset_events()
422 assert for_c_return() == 5
423 assert events() == 54
424}
425
426fn test_for_c_multi_init_return_frees_all_init_vars_after_body() {
427 reset_events()
428 assert for_c_multi_init_return() == 5
429 assert events() == 534
430}
431
432fn test_for_c_returned_init_string_is_not_freed_before_return() {
433 reset_events()
434 value := for_c_return_init_string()
435 assert value == 'ababab'
436 assert events() == 5
437}
438
439fn test_for_c_multi_init_returned_second_is_not_freed_before_return() {
440 reset_events()
441 value := for_c_multi_init_return_second()
442 assert value.id == 3
443 assert events() == 54
444}
445
446fn test_for_c_multi_init_returned_second_string_is_not_freed_before_return() {
447 reset_events()
448 value := for_c_multi_init_return_second_string()
449 assert value == 'yyy'
450 assert events() == 5
451}
452
453fn test_for_c_returned_init_string_field_preserves_owner() {
454 reset_events()
455 value := for_c_return_init_field_string()
456 assert value == 'xxxx'
457 assert events() == 5
458}
459
460fn test_for_c_returned_init_alias_string_field_preserves_owner() {
461 reset_events()
462 value := for_c_return_init_field_alias_string()
463 assert string(value) == 'xxxx'
464 assert events() == 5
465}
466
467fn test_for_c_returned_init_scalar_field_still_frees_owner() {
468 reset_events()
469 value := for_c_return_init_field_id()
470 assert value == 4
471 assert events() == 54
472}
473
474fn test_for_c_branch_return_body_still_frees_init() {
475 reset_events()
476 value := for_c_branch_return_body_after_init_path(false)
477 assert value.id == 5
478 assert events() == 4
479}
480
481fn test_for_c_multi_init_branch_return_body_still_frees_all_init_vars() {
482 reset_events()
483 value := for_c_multi_init_branch_return_body_after_second_path(false)
484 assert value.id == 5
485 assert events() == 34
486}
487
488fn test_for_c_branch_return_body_string_path_still_frees_init() {
489 reset_events()
490 value := for_c_branch_return_body_after_init_string_path(false)
491 assert value == 'body'
492 assert events() == 5
493}
494