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