1
2 import core.stdc.stdio;
3
4 struct S { int a,b,c,d; }
5
6 alias int delegate() dg_t;
7 alias int delegate(int) dg1_t;
8
fill()9 void fill()
10 {
11 int[100] x;
12 }
13
14 /************************************/
15
foo()16 dg_t foo()
17 {
18 int x = 7;
19
20 int bar()
21 {
22 return x + 3;
23 }
24
25 return &bar;
26 }
27
test1()28 void test1()
29 {
30 dg_t dg = foo();
31 fill();
32 printf("bar = %d\n", dg());
33 assert(dg() == 10);
34 }
35
36 /************************************/
37
foo2()38 dg_t foo2()
39 {
40 dg_t abc()
41 {
42 int x = 7;
43
44 int bar()
45 {
46 return x + 3;
47 }
48
49 return &bar;
50 }
51
52 return abc();
53 }
54
test2()55 void test2()
56 {
57 dg_t dg = foo2();
58 fill();
59 printf("bar = %d\n", dg());
60 assert(dg() == 10);
61 }
62
63 /************************************/
64
foo3()65 dg_t foo3()
66 {
67 dg_t abc(int x)
68 {
69 int bar()
70 {
71 return x + 3;
72 }
73
74 return &bar;
75 }
76
77 return abc(7);
78 }
79
test3()80 void test3()
81 {
82 dg_t dg = foo3();
83 fill();
84 printf("bar = %d\n", dg());
85 assert(dg() == 10);
86 }
87
88 /************************************/
89
foo4()90 dg_t foo4()
91 {
92 S s;
93
94 s = S(4,5,6,7);
95
96 dg_t abc(S t)
97 {
98 int bar()
99 {
100 return t.d + 3;
101 }
102
103 return &bar;
104 }
105
106 return abc(s);
107 }
108
test4()109 void test4()
110 {
111 dg_t dg = foo4();
112 fill();
113 printf("bar = %d\n", dg());
114 assert(dg() == 10);
115 }
116
117 /************************************/
118
test5()119 void test5()
120 {
121 int x = 7;
122
123 dg_t abc(ref int y)
124 {
125 int bar()
126 {
127 y += 4;
128 return y + 3;
129 }
130
131 return &bar;
132 }
133
134 dg_t dg = abc(x);
135 fill();
136 assert(x == 7);
137 auto i = dg();
138 assert(x == 11);
139 assert(i == 14);
140
141 x = 8;
142 i = dg();
143 assert(x == 12);
144 assert(i == 15);
145 }
146
147 /************************************/
148
test6()149 void test6()
150 {
151 int x = 7;
152
153 dg_t abc(out int y)
154 {
155 int bar()
156 {
157 y += 4;
158 return y + 3;
159 }
160
161 return &bar;
162 }
163
164 dg_t dg = abc(x);
165 fill();
166
167 assert(x == 0);
168 auto i = dg();
169 assert(x == 4);
170 assert(i == 7);
171
172 x = 8;
173 i = dg();
174 assert(x == 12);
175 assert(i == 15);
176 }
177
178 /************************************/
179
test7()180 void test7()
181 {
182 int[3] a = [10,11,12];
183
184 dg_t abc(int[3] y)
185 {
186 int bar()
187 {
188 y[2] += 4;
189 return y[2] + 3;
190 }
191
192 return &bar;
193 }
194
195 dg_t dg = abc(a);
196 fill();
197
198 assert(a[2] == 12);
199 auto i = dg();
200 assert(a[2] == 12);
201 assert(i == 19);
202 }
203
204 /************************************/
205
test8()206 void test8()
207 {
208 S s = S(7,8,9,10);
209
210 dg_t abc(ref S t)
211 {
212 int bar()
213 {
214 t.d += 4;
215 return t.c + 3;
216 }
217
218 return &bar;
219 }
220
221 dg_t dg = abc(s);
222 fill();
223
224 assert(s.d == 10);
225 auto i = dg();
226 assert(s.d == 14);
227 assert(i == 12);
228 }
229
230 /************************************/
231
foo9(out dg_t dg)232 S foo9(out dg_t dg)
233 {
234 S s1 = S(7,8,9,10);
235
236 dg_t abc()
237 {
238 int bar()
239 {
240 s1.d += 4;
241 return s1.c + 3;
242 }
243
244 return &bar;
245 }
246
247 dg = abc();
248 return s1;
249 }
250
test9()251 void test9()
252 {
253 dg_t dg;
254
255 S s = foo9(dg);
256 fill();
257 assert(s.a == 7);
258 assert(s.b == 8);
259 assert(s.c == 9);
260 assert(s.d == 10);
261
262 auto i = dg();
263 assert(s.d == 10);
264 assert(i == 12);
265 }
266
267 /************************************/
268
foo10()269 dg_t foo10()
270 {
271 dg_t abc()
272 {
273 int x = 7;
274
275 int bar()
276 {
277 int def()
278 {
279 return x + 3;
280 }
281 return def();
282 }
283
284 return &bar;
285 }
286
287 return abc();
288 }
289
test10()290 void test10()
291 {
292 dg_t dg = foo10();
293 fill();
294 printf("bar = %d\n", dg());
295 assert(dg() == 10);
296 }
297
298
299 /************************************/
300
foo11()301 dg_t foo11()
302 {
303 int x = 7;
304
305 class T
306 {
307 int bar()
308 {
309 return x + 3;
310 }
311 }
312
313 T t = new T;
314
315 return &t.bar;
316 }
317
test11()318 void test11()
319 {
320 dg_t dg = foo11();
321 fill();
322 printf("bar = %d\n", dg());
323 assert(dg() == 10);
324 }
325
326 /************************************/
327
foo12()328 dg_t foo12()
329 {
330 int x = 7;
331
332 class T
333 {
334 int bar()
335 {
336 return x + 3;
337 }
338
339 int xyz()
340 {
341 return bar();
342 }
343 }
344
345 T t = new T;
346
347 return &t.xyz;
348 }
349
test12()350 void test12()
351 {
352 dg_t dg = foo12();
353 fill();
354 printf("bar = %d\n", dg());
355 assert(dg() == 10);
356 }
357
358 /************************************/
359
foo13()360 dg_t foo13()
361 {
362 int x = 7;
363
364 class T
365 {
366 int xyz()
367 {
368 int bar()
369 {
370 return x + 3;
371 }
372
373 return bar();
374 }
375 }
376
377 T t = new T;
378
379 return &t.xyz;
380 }
381
test13()382 void test13()
383 {
384 dg_t dg = foo13();
385 fill();
386 printf("bar = %d\n", dg());
387 assert(dg() == 10);
388 }
389
390
391 /************************************/
392
foo14()393 dg_t foo14()
394 {
395 class T
396 {
397 int xyz()
398 {
399 int x = 7;
400
401 int bar()
402 {
403 return x + 3;
404 }
405
406 return bar();
407 }
408 }
409
410 T t = new T;
411
412 return &t.xyz;
413 }
414
test14()415 void test14()
416 {
417 dg_t dg = foo14();
418 fill();
419 printf("bar = %d\n", dg());
420 assert(dg() == 10);
421 }
422
423 /************************************/
424
foo15()425 dg_t foo15()
426 {
427 class T
428 {
429 int x = 7;
430
431 int xyz()
432 {
433 int bar()
434 {
435 return x + 3;
436 }
437
438 return bar();
439 }
440 }
441
442 T t = new T;
443
444 return &t.xyz;
445 }
446
test15()447 void test15()
448 {
449 dg_t dg = foo15();
450 fill();
451 printf("bar = %d\n", dg());
452 assert(dg() == 10);
453 }
454
455 /************************************/
456
foo16()457 dg_t foo16()
458 {
459 int a = 5;
460
461 class T
462 {
463 int x = 7;
464
465 int xyz()
466 {
467 int y = 8;
468 int bar()
469 {
470 return a + x + y + 3;
471 }
472
473 return bar();
474 }
475 }
476
477 T t = new T;
478
479 return &t.xyz;
480 }
481
test16()482 void test16()
483 {
484 dg_t dg = foo16();
485 fill();
486 printf("bar = %d\n", dg());
487 assert(dg() == 23);
488 }
489
490 /************************************/
491
foo17()492 dg_t foo17()
493 {
494 int a = 5;
495
496 class T
497 {
498 int x = 7;
499
500 dg_t xyz()
501 {
502 int y = 8;
503
504 int bar()
505 {
506 return a + x + y + 3;
507 }
508
509 return &bar;
510 }
511 }
512
513 T t = new T;
514
515 return t.xyz();
516 }
517
test17()518 void test17()
519 {
520 dg_t dg = foo17();
521 fill();
522 printf("bar = %d\n", dg());
523 assert(dg() == 23);
524 }
525
526 /************************************/
527
528 dg_t dg18;
529
bar18()530 void bar18()
531 {
532 int a = 7;
533 int foo() { return a + 3; }
534
535 dg18 = &foo;
536 int i = dg18();
537 assert(i == 10);
538 }
539
test18()540 void test18()
541 {
542 bar18();
543 fill();
544 int i = dg18();
545 assert(i == 10);
546 }
547
548 /************************************/
549
abc19(void delegate ()dg)550 void abc19(void delegate() dg)
551 {
552 dg();
553 dg();
554 dg();
555 }
556
557 struct S19
558 {
callS19559 static S19 call(int v)
560 {
561 S19 result;
562
563 result.v = v;
564 void nest()
565 {
566 result.v += 1;
567 }
568 abc19(&nest);
569 return result;
570 }
571 int a;
572 int v;
573 int x,y,z;
574 }
575
foo19()576 int foo19()
577 {
578 auto s = S19.call(5);
579 return s.v;
580 }
581
test19()582 void test19()
583 {
584 int i = foo19();
585 printf("%d\n", i);
586 assert(i == 8);
587 }
588
589 /************************************/
590
enforce20(lazy int msg)591 void enforce20(lazy int msg)
592 {
593 }
594
595
test20()596 void test20()
597 {
598 int x;
599 foreach (j; 0 .. 10)
600 {
601 printf("%d\n", j);
602 assert(j == x);
603 x++;
604 enforce20(j);
605 }
606 }
607
608 /************************************/
609
thrash21()610 void thrash21() { char[128] x = '\xfe'; }
611
612 void delegate() dg21;
613 int g_input = 11, g_output;
614
f21()615 void f21()
616 {
617 int i = g_input + 2;
618
619 class X
620 {
621 // both 'private' and 'final' to make non-virtual
622 private final void actual()
623 {
624 g_output = i;
625 }
626
627 void go()
628 {
629 actual();
630 }
631 }
632
633 dg21 = & (new X).go;
634 }
635
test21()636 void test21()
637 {
638 f21();
639 thrash21();
640 dg21();
641 assert(g_output == 13);
642 }
643
644 /************************************/
645
thrash22()646 void thrash22() { char[128] x = '\xfe'; }
647 int gi22;
648 void delegate() dg22;
649
650 class A22
651 {
652 int x = 42;
653
am()654 void am()
655 {
656 int j; /* Making f access this variable causes f's chain to be am's
657 frame. Otherwise, f's chain would be the A instance. */
658 void f()
659 {
660 int k = j;
661
662 void g()
663 {
664 class B
665 {
666 void bm()
667 {
668 gi22 = x; /* No checkedNestedReference for A.am.this,
669 so it is never placed in a closure. */
670 }
671 }
672
673 (new B).bm();
674 }
675
676 dg22 = &g;
677 }
678
679 f();
680 }
681 }
682
test22()683 void test22()
684 {
685 (new A22).am();
686 thrash22();
687 dg22();
688 assert(gi22 == 42);
689 }
690
691 /************************************/
692 // 1759
693
test1759()694 void test1759()
695 {
696 struct S { int a, b, c; }
697 struct SS { S obj; }
698
699 static int delegate() makeSum1(S s)
700 {
701 with (s) return { return a + b + c; };
702 }
703 static int delegate() makeSum2(S[1] sa)
704 {
705 with (sa[0]) return { return a + b + c; };
706 }
707 static int delegate() makeSum3(SS ss)
708 {
709 with (ss.obj) return { return a + b + c; };
710 }
711 static int delegate() makeSum4(SS[1] ssa)
712 {
713 with (ssa[0].obj) return { return a + b + c; };
714 }
715
716 S s = {15, 30, 45};
717 SS ss = {s};
718 int delegate() sum;
719
720 sum = makeSum1(s); assert(sum() == 90);
721 sum = makeSum2([s]); assert(sum() == 90);
722 sum = makeSum3(ss); assert(sum() == 90);
723 sum = makeSum4([ss]); assert(sum() == 90);
724 }
725
726 /************************************/
727 // 1841
728
delegate()729 int delegate() foo1841()
730 {
731 int stack;
732 int heap = 3;
733
734 int nested_func()
735 {
736 ++heap;
737 return heap;
738 }
739 return delegate int() { return nested_func(); };
740 }
741
delegate()742 int delegate() foo1841b()
743 {
744 int stack;
745 int heap = 7;
746
747 int nested_func()
748 {
749 ++heap;
750 return heap;
751 }
752 int more_nested() { return nested_func(); }
753 return delegate int() { return more_nested(); };
754 }
755
test1841()756 void test1841()
757 {
758 auto z = foo1841();
759 auto p = foo1841();
760 assert(z() == 4);
761 p();
762 assert(z() == 5);
763 z = foo1841b();
764 p = foo1841b();
765 assert(z() == 8);
766 p();
767 assert(z() == 9);
768 }
769
770 /************************************/
771 // 5911
772
writeln5911(const (char)[]str)773 void writeln5911(const(char)[] str) {}
774
logout5911(lazy const (char)[]msg)775 void logout5911(lazy const(char)[] msg) { writeln5911(msg); }
776
test5911()777 void test5911()
778 {
779 string str = "hello world";
780 logout5911((){ return str; }()); // closure 1
781
782 try
783 {
784 throw new Exception("exception!!");
785 }
786 catch (Exception e)
787 {
788 assert(e !is null);
789 logout5911(e.toString()); // closure2 SEGV : e is null.
790 }
791 }
792
793 /************************************/
794 // 9685
795
get9685a(alias fun)796 auto get9685a(alias fun)()
797 {
798 int x = 10;
799 struct Foo
800 {
801 size_t data;
802
803 @property clone()
804 {
805 return Foo(15);
806 }
807 }
808 return Foo(5);
809 }
test9685a()810 void test9685a()
811 {
812 uint a = 42;
813 auto bar = get9685a!(() => a)();
814 auto qux = bar.clone;
815 //printf("bar context pointer : %p\n", bar.tupleof[$-1]);
816 //printf("qux context pointer : %p\n", qux.tupleof[$-1]);
817 assert(bar.tupleof[$-1] == qux.tupleof[$-1]);
818 assert(qux.data == 15);
819 }
820
get9685b(alias fun)821 auto get9685b(alias fun)()
822 {
823 int x = 10;
824 struct Foo
825 {
826 size_t data;
827
828 @property clone()
829 {
830 return Foo(data + x);
831 }
832 }
833 return Foo(5);
834 }
test9685b()835 void test9685b()
836 {
837 uint a = 42;
838 auto bar = get9685b!(() => a)();
839 auto qux = bar.clone;
840 //printf("bar context pointer : %p\n", bar.tupleof[$-1]);
841 //printf("qux context pointer : %p\n", qux.tupleof[$-1]);
842 assert(bar.tupleof[$-1] == qux.tupleof[$-1]);
843 assert(qux.data == 15);
844 }
845
846 /************************************/
847 // 12406
848
createDg12406()849 auto createDg12406()
850 {
851 static struct Dg
852 {
853 Dg delegate() action;
854 }
855
856 static void fn(void delegate()) { }
857
858 int x; fn({ x++; }); // required
859
860 Dg dg;
861
862 Dg createDg2()
863 {
864 int x; void unusedFun() { x++; } // required
865
866 return Dg(() => dg); // lambda returns garbage instead of dg
867 }
868
869 return dg = Dg(&createDg2);
870 }
871
test12406()872 void test12406()
873 {
874 auto dgs = [createDg12406()];
875 //printf("dgs[%2d].action = %p:%p\n", 0, dgs[$-1].action.ptr, dgs[$-1].action.funcptr);
876 foreach (i; 1 .. 10+1)
877 {
878 dgs ~= dgs[i-1].action();
879 //printf("dgs[%2d].action = %p:%p\n", i, dgs[$-1].action.ptr, dgs[$-1].action.funcptr);
880 }
881
882 foreach (i, dgx; dgs)
883 {
884 if (i % 2 == 0)
885 {
886 // All closures are equal with dgs[0].
887 assert(dgx.action.ptr is dgs[0].action.ptr);
888 assert(dgx.action.funcptr is dgs[0].action.funcptr); // is: createDg2
889 }
890 else
891 {
892 // Each closures has unique context.
893 for (size_t j = i + 2; j < dgs.length; j += 2)
894 assert(dgx.action.ptr !is dgs[j].action.ptr);
895 assert(dgx.action.funcptr is dgs[1].action.funcptr); // is: lambda () => dg
896 }
897 }
898 }
899
900 /************************************/
901 // 14730
902
test14730()903 void test14730()
904 {
905 static auto makeS(int x)
906 {
907 struct S
908 {
909 int n;
910 int get() { return x; } // x will be a closure variable
911 }
912 return S(x);
913 }
914 auto s = makeS(1);
915 assert(s.get() == 1);
916 // By inlining get() function call, it's rewritten to:
917 // assert(*(s.tupleof[$-1] + x.offset) == 1);
918 // --> In DotVarExp::toElem(), x->offset should be already nonzero.
919 }
920
921 // ----
922
923 // This is questionable case. Currently it works without any errors,
924 // but not sure it's really intentional
925
S14730x(alias f)926 struct S14730x(alias f)
927 {
928 auto foo()() { return f(0); }
929
930 void dummy() {}
931 }
932
makeS14730x()933 auto makeS14730x() //@nogc
934 {
935 int x = 10;
936 S14730x!(a => x) s;
937 //assert(s.foo() == 10);
938 return s;
939 }
940
test14730x()941 void test14730x()
942 {
943 auto s = makeS14730x();
944 assert(s.tupleof[$-1] !is null);
945
946 // instantiationg foo outside of makeS will place the variable x in closure
947 // *after* the semantic3 completion of makeS() function.
948 assert(s.foo() == 10);
949 }
950
951 /************************************/
952
main()953 int main()
954 {
955 test1();
956 test2();
957 test3();
958 test4();
959 test5();
960 test6();
961 test7();
962 test8();
963 test9();
964 test10();
965 test11();
966 test12();
967 test13();
968 test14();
969 test15();
970 test16();
971 test17();
972 test18();
973 test19();
974 test20();
975 test21();
976 test22();
977 test1759();
978 test1841();
979 test5911();
980 test9685a();
981 test9685b();
982 test12406();
983 test14730();
984 test14730x();
985
986 printf("Success\n");
987 return 0;
988 }
989