1 /*
2 TEST_OUTPUT:
3 ---
4 int
5 double
6 foobar7406(T)
7 test7406()
8 int
9 foobar7406(T)
10 int
11 test7406()
12 ---
13 */
14
15 extern(C) int printf(const char* fmt, ...);
16
17 /***************************************/
18
test1()19 void test1()
20 {
21 char[] a;
22
23 int foo()
24 {
25 printf("foo\n");
26 a ~= "foo";
27 return 10;
28 }
29
30 foreach (i; 0 .. foo())
31 {
32 printf("%d\n", i);
33 a ~= cast(char)('0' + i);
34 }
35 assert(a == "foo0123456789");
36
37 foreach_reverse (i; 0 .. foo())
38 {
39 printf("%d\n", i);
40 a ~= cast(char)('0' + i);
41 }
42 assert(a == "foo0123456789foo9876543210");
43 }
44
45 /***************************************/
46 // 2411
47
48 struct S2411
49 {
50 int n;
51 string s;
52 }
53
test2411()54 void test2411()
55 {
56 S2411 s;
57 assert(s.n == 0);
58 assert(s.s == "");
59 foreach (i, ref e; s.tupleof)
60 {
61 static if (i == 0)
62 e = 10;
63 static if (i == 1)
64 e = "str";
65 }
66 assert(s.n == 10);
67 assert(s.s == "str");
68 }
69
70 /***************************************/
71 // 2442
72
canForeach(T,E)73 template canForeach(T, E)
74 {
75 enum canForeach = __traits(compiles,
76 {
77 foreach(a; new T)
78 {
79 static assert(is(typeof(a) == E));
80 }
81 });
82 }
83
test2442()84 void test2442()
85 {
86 struct S1
87 {
88 int opApply(int delegate(ref const(int) v) dg) const { return 0; }
89 int opApply(int delegate(ref int v) dg) { return 0; }
90 }
91 S1 ms1;
92 const S1 cs1;
93 foreach (x; ms1) { static assert(is(typeof(x) == int)); }
94 foreach (x; cs1) { static assert(is(typeof(x) == const int)); }
95
96 struct S2
97 {
98 int opApply(int delegate(ref int v) dg) { return 0; }
99 int opApply(int delegate(ref long v) dg) { return 0; }
100 }
101 S2 ms2;
102 static assert(!__traits(compiles, { foreach ( x; ms2) {} })); // ambiguous
103 static assert( __traits(compiles, { foreach (int x; ms2) {} }));
104
105 struct S3
106 {
107 int opApply(int delegate(ref int v) dg) const { return 0; }
108 int opApply(int delegate(ref int v) dg) shared const { return 0; }
109 }
110 immutable S3 ms3;
111 static assert(!__traits(compiles, { foreach (int x; ms3) {} })); // ambiguous
112
113 // from https://github.com/dlang/dmd/pull/120
114 static class C
115 {
116 int opApply(int delegate(ref int v) dg) { return 0; }
117 int opApply(int delegate(ref const int v) dg) const { return 0; }
118 int opApply(int delegate(ref immutable int v) dg) immutable { return 0; }
119 int opApply(int delegate(ref shared int v) dg) shared { return 0; }
120 int opApply(int delegate(ref shared const int v) dg) shared const { return 0; }
121 }
122 static class D
123 {
124 int opApply(int delegate(ref int v) dg) const { return 0; }
125 }
126 static class E
127 {
128 int opApply(int delegate(ref int v) dg) shared const { return 0; }
129 }
130
131 static assert( canForeach!( C , int ));
132 static assert( canForeach!( const(C) , const(int) ));
133 static assert( canForeach!( immutable(C) , immutable(int) ));
134 static assert( canForeach!( shared(C) , shared(int) ));
135 static assert( canForeach!(shared(const(C)), shared(const(int))));
136
137 static assert( canForeach!( D , int));
138 static assert( canForeach!( const(D) , int));
139 static assert( canForeach!( immutable(D) , int));
140 static assert(!canForeach!( shared(D) , int));
141 static assert(!canForeach!(shared(const(D)), int));
142
143 static assert(!canForeach!( E , int));
144 static assert(!canForeach!( const(E) , int));
145 static assert( canForeach!( immutable(E) , int));
146 static assert( canForeach!( shared(E) , int));
147 static assert( canForeach!(shared(const(E)), int));
148 }
149
150 /***************************************/
151 // 2443
152
153 struct S2443
154 {
155 int[] arr;
opApplyS2443156 int opApply(int delegate(size_t i, ref int v) dg)
157 {
158 int result = 0;
159 foreach (i, ref x; arr)
160 {
161 if ((result = dg(i, x)) != 0)
162 break;
163 }
164 return result;
165 }
166 }
167
test2443()168 void test2443()
169 {
170 S2443 s;
171 foreach (i, ref v; s) {}
172 foreach (i, v; s) {}
173 static assert(!__traits(compiles, { foreach (ref i, ref v; s) {} }));
174 static assert(!__traits(compiles, { foreach (ref i, v; s) {} }));
175 }
176
177 /***************************************/
178 // 3187
179
180 class Collection
181 {
opApply(int delegate (ref Object)a)182 int opApply(int delegate(ref Object) a)
183 {
184 return 0;
185 }
186 }
187
testForeach(Collection level1,Collection level2)188 Object testForeach(Collection level1, Collection level2)
189 {
190 foreach (first; level1) {
191 foreach (second; level2)
192 return second;
193 }
194 return null;
195 }
196
test3187()197 void test3187()
198 {
199 testForeach(new Collection, new Collection);
200 }
201
202 /***************************************/
203 // 4090
204
test4090a()205 void test4090a()
206 {
207 double[10] arr = 1;
208 double tot = 0;
209
210 static assert(!__traits(compiles, {
211 foreach (immutable ref x; arr) {}
212 }));
213 foreach (const ref x; arr)
214 {
215 static assert(is(typeof(x) == const double));
216 tot += x;
217 }
218 foreach (immutable x; arr)
219 {
220 static assert(is(typeof(x) == immutable double));
221 tot += x;
222 }
223 assert(tot == 1*10 + 1*10);
224 }
225
test4090b()226 void test4090b()
227 {
228 int tot = 0;
229
230 static assert(!__traits(compiles, {
231 foreach (immutable ref x; 1..11) {}
232 }));
233 foreach (const ref x; 1..11)
234 {
235 static assert(is(typeof(x) == const int));
236 tot += x;
237 }
238 foreach (immutable x; 1..11)
239 {
240 static assert(is(typeof(x) == immutable int));
241 tot += x;
242 }
243 assert(tot == 55 + 55);
244 }
245
246 /***************************************/
247 // 5605
248
249 struct MyRange
250 {
251 int theOnlyOne;
252
emptyMyRange253 @property bool empty() const
254 {
255 return true;
256 }
257
frontMyRange258 @property ref int front()
259 {
260 return theOnlyOne;
261 }
262
popFrontMyRange263 void popFront()
264 {}
265 }
266
267 struct MyCollection
268 {
opSlice()269 MyRange opSlice() const
270 {
271 return MyRange();
272 }
273 }
274
test5605()275 void test5605()
276 {
277 auto coll = MyCollection();
278
279 foreach (i; coll) { // <-- compilation error
280 // ...
281 }
282 }
283
284 /***************************************/
285 // 7004
286
func7004(A...)287 void func7004(A...)(A args)
288 {
289 foreach (i, e; args){} // OK
290 foreach (uint i, e; args){} // OK
291 foreach (size_t i, e; args){} // NG
292 }
test7004()293 void test7004()
294 {
295 func7004(1, 3.14);
296 }
297
298 /***************************************/
299 // 7406
300
TypeTuple7406(T...)301 template TypeTuple7406(T...)
302 {
303 alias T TypeTuple7406;
304 }
305
foobar7406(T)306 template foobar7406(T)
307 {
308 enum foobar = 2;
309 }
310
test7406()311 void test7406()
312 {
313 foreach (sym; TypeTuple7406!(int, double)) // OK
314 pragma(msg, sym.stringof);
315
316 foreach (sym; TypeTuple7406!(foobar7406)) // OK
317 pragma(msg, sym.stringof);
318
319 foreach (sym; TypeTuple7406!(test7406)) // OK
320 pragma(msg, sym.stringof);
321
322 foreach (sym; TypeTuple7406!(int, foobar7406)) // Error: type int has no value
323 pragma(msg, sym.stringof);
324
325 foreach (sym; TypeTuple7406!(int, test7406)) // Error: type int has no value
326 pragma(msg, sym.stringof);
327 }
328
329 /***************************************/
330 // 6659
331
test6659()332 void test6659()
333 {
334 static struct Iter
335 {
336 ~this()
337 {
338 ++_dtor;
339 }
340
341 bool opCmp(ref const Iter rhs) { return _pos == rhs._pos; }
342 void opUnary(string op:"++")() { ++_pos; }
343 size_t _pos;
344
345 static size_t _dtor;
346 }
347
348 foreach (ref iter; Iter(0) .. Iter(10))
349 {
350 assert(Iter._dtor == 0);
351 }
352 assert(Iter._dtor == 2);
353
354 Iter._dtor = 0; // reset
355
356 for (auto iter = Iter(0), limit = Iter(10); iter != limit; ++iter)
357 {
358 assert(Iter._dtor == 0);
359 }
360 assert(Iter._dtor == 2);
361 }
362
test6659a()363 void test6659a()
364 {
365 auto value = 0;
366 try
367 {
368 for ({scope(success) { assert(value == 1); value = 2;} } true; )
369 {
370 value = 1;
371 break;
372 }
373 assert(value == 2);
374 }
375 catch (Exception e)
376 {
377 assert(0);
378 }
379 assert(value == 2);
380 }
381
test6659b()382 void test6659b()
383 {
384 auto value = 0;
385 try
386 {
387 for ({scope(failure) value = 1;} true; )
388 {
389 throw new Exception("");
390 }
391 assert(0);
392 }
393 catch (Exception e)
394 {
395 assert(e);
396 }
397 assert(value == 1);
398 }
399
test6659c()400 void test6659c()
401 {
402 auto value = 0;
403 try
404 {
405 for ({scope(exit) value = 1;} true; )
406 {
407 throw new Exception("");
408 }
409 assert(0);
410 }
411 catch (Exception e)
412 {
413 assert(e);
414 }
415 assert(value == 1);
416 }
417
418 /***************************************/
419
420 // 10221
421
test10221()422 void test10221()
423 {
424 // All of these should work, but most are too slow. Just check they compile.
425 foreach(char i; char.min..char.max+1) {}
426 if (0) foreach(wchar i; wchar.min..wchar.max+1) {}
427 if (0) foreach(dchar i; dchar.min..dchar.max+1) {}
428 foreach(byte i; byte.min..byte.max+1) {}
429 foreach(ubyte i; ubyte.min..ubyte.max+1) {}
430 if (0) foreach(short i; short.min..short.max+1) {}
431 if (0) foreach(ushort i; ushort.min..ushort.max+1) {}
432 if (0) foreach(int i; int.min..int.max+1U) {}
433 if (0) foreach(uint i; uint.min..uint.max+1L) {}
434 if (0) foreach(long i; long.min..long.max+1UL) {}
435
436 foreach_reverse(char i; char.min..char.max+1) { assert(i == typeof(i).max); break; }
437 foreach_reverse(wchar i; wchar.min..wchar.max+1) { assert(i == typeof(i).max); break; }
438 foreach_reverse(dchar i; dchar.min..dchar.max+1) { assert(i == typeof(i).max); break; }
439 foreach_reverse(byte i; byte.min..byte.max+1) { assert(i == typeof(i).max); break; }
440 foreach_reverse(ubyte i; ubyte.min..ubyte.max+1) { assert(i == typeof(i).max); break; }
441 foreach_reverse(short i; short.min..short.max+1) { assert(i == typeof(i).max); break; }
442 foreach_reverse(ushort i; ushort.min..ushort.max+1) { assert(i == typeof(i).max); break; }
443 foreach_reverse(int i; int.min..int.max+1U) { assert(i == typeof(i).max); break; }
444 foreach_reverse(uint i; uint.min..uint.max+1L) { assert(i == typeof(i).max); break; }
445 foreach_reverse(long i; long.min..long.max+1UL) { assert(i == typeof(i).max); break; }
446 }
447
448 /***************************************/
449 // 7814
450
451 struct File7814
452 {
~thisFile7814453 ~this(){}
454 }
455
456 struct ByLine7814
457 {
458 File7814 file;
459
460 // foreach interface
empty()461 @property bool empty() const { return true; }
front()462 @property char[] front() { return null; }
popFront()463 void popFront(){}
464 }
465
test7814()466 void test7814()
467 {
468 int dummy;
469 ByLine7814 f;
470 foreach (l; f) {
471 scope(failure) // 'failure' or 'success' fails, but 'exit' works
472 dummy = -1;
473 dummy = 0;
474 }
475 }
476
477 /***************************************/
478 // 10049
479
480 struct ByLine10049
481 {
emptyByLine10049482 bool empty() { return true; }
frontByLine10049483 string front() { return null; }
popFrontByLine10049484 void popFront() {}
485
~thisByLine10049486 ~this() {} // necessary
487 }
488
test10049()489 void test10049()
490 {
491 ByLine10049 r;
492 foreach (line; r)
493 {
494 doNext:
495 {}
496 }
497 }
498
499 /******************************************/
500
T11955(T...)501 struct T11955(T...) { T field; alias field this; }
502
503 alias X11955 = uint;
504
505 struct S11955
506 {
507 enum empty = false;
508 T11955!(uint, uint) front;
popFrontS11955509 void popFront() {}
510 }
511
test11955()512 void test11955()
513 {
514 foreach(X11955 i, v; S11955()) {}
515 }
516
517 /******************************************/
518 // 6652
519
test6652()520 void test6652()
521 {
522 size_t sum;
523 foreach (i; 0 .. 10)
524 sum += i++; // 0123456789
525 assert(sum == 45);
526
527 sum = 0;
528 foreach (ref i; 0 .. 10)
529 sum += i++; // 02468
530 assert(sum == 20);
531
532 sum = 0;
533 foreach_reverse (i; 0 .. 10)
534 sum += i--; // 9876543210
535 assert(sum == 45);
536
537 sum = 0;
538 foreach_reverse (ref i; 0 .. 10)
539 sum += i--; // 97531
540 assert(sum == 25);
541
542 enum ary = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
543 sum = 0;
544 foreach (i, v; ary)
545 {
546 assert(i == v);
547 sum += i++; // 0123456789
548 }
549 assert(sum == 45);
550
551 sum = 0;
552 foreach (ref i, v; ary)
553 {
554 assert(i == v);
555 sum += i++; // 02468
556 }
557 assert(sum == 20);
558
559 sum = 0;
560 foreach_reverse (i, v; ary)
561 {
562 assert(i == v);
563 sum += i--; // 9876543210
564 }
565 assert(sum == 45);
566
567 sum = 0;
568 foreach_reverse (ref i, v; ary)
569 {
570 assert(i == v);
571 sum += i--; // 97531
572 }
573 assert(sum == 25);
574
575 static struct Iter
576 {
577 ~this()
578 {
579 ++_dtorCount;
580 }
581
582 bool opCmp(ref const Iter rhs)
583 {
584 return _pos == rhs._pos;
585 }
586
587 void opUnary(string op)() if(op == "++" || op == "--")
588 {
589 mixin(op ~ q{_pos;});
590 }
591
592 size_t _pos;
593 static size_t _dtorCount;
594 }
595
596 Iter._dtorCount = sum = 0;
597 foreach (v; Iter(0) .. Iter(10))
598 sum += v._pos++; // 0123456789
599 assert(sum == 45 && Iter._dtorCount == 12);
600
601 Iter._dtorCount = sum = 0;
602 foreach (ref v; Iter(0) .. Iter(10))
603 sum += v._pos++; // 02468
604 assert(sum == 20 && Iter._dtorCount == 2);
605
606 // additional dtor calls due to unnecessary postdecrements
607 Iter._dtorCount = sum = 0;
608 foreach_reverse (v; Iter(0) .. Iter(10))
609 sum += v._pos--; // 9876543210
610 assert(sum == 45 && Iter._dtorCount >= 12);
611
612 Iter._dtorCount = sum = 0;
613 foreach_reverse (ref v; Iter(0) .. Iter(10))
614 sum += v._pos--; // 97531
615 assert(sum == 25 && Iter._dtorCount >= 2);
616 }
617
618 /***************************************/
619 // 8595
620
621 struct OpApply8595
622 {
opApplyOpApply8595623 int opApply(int delegate(ref int) dg)
624 {
625 assert(0);
626 }
627 }
628
test8595()629 string test8595()
630 {
631 foreach (elem; OpApply8595.init)
632 {
633 static assert(is(typeof(return) == string));
634 }
635 assert(0);
636 }
637
638 /***************************************/
639 // 9068
640
641 struct Foo9068
642 {
643 static int[] destroyed;
644 int x;
~thisFoo9068645 ~this() { destroyed ~= x; }
646 }
647
648 struct SimpleCounter9068
649 {
650 static int destroyedCount;
651 enum int limit = 5;
652 int counter;
~this()653 ~this() { destroyedCount++; }
654
655 // Range primitives.
empty()656 @property bool empty() const { return counter >= limit; }
front()657 @property int front() { return counter; }
popFront()658 void popFront() { counter++; }
659 }
660
test9068()661 void test9068()
662 {
663 //----------------------------------------
664 // There was never a bug in this case (no range).
665 int sum;
666 loop_simple:
667 foreach (i; [10, 20])
668 {
669 sum += i;
670 break loop_simple;
671 }
672 assert(sum == 10);
673
674 //----------------------------------------
675 // There was a bug with loops over ranges.
676 int last = -1;
677 X: foreach (i; SimpleCounter9068())
678 {
679 switch(i)
680 {
681 case 3:
682 break X;
683 default:
684 last = i;
685 }
686 }
687 assert(last == 2);
688 assert(SimpleCounter9068.destroyedCount == 1);
689
690 //----------------------------------------
691 // Simpler case: the compiler error had nothing to do with the switch.
692 last = -1;
693 loop_with_range:
694 foreach (i; SimpleCounter9068())
695 {
696 last = i;
697 break loop_with_range;
698 }
699 assert(last == 0);
700 assert(SimpleCounter9068.destroyedCount == 2);
701
702 //----------------------------------------
703 // Test with destructors: the loop is implicitly wrapped into two
704 // try/finally clauses.
705 loop_with_dtors:
706 for (auto x = Foo9068(4), y = Foo9068(5); x.x != 10; ++x.x)
707 {
708 if (x.x == 8)
709 break loop_with_dtors;
710 }
711 assert(Foo9068.destroyed == [5, 8]);
712 Foo9068.destroyed = null;
713
714 //----------------------------------------
715 // Same with an unlabelled break.
716 for (auto x = Foo9068(4), y = Foo9068(5); x.x != 10; ++x.x)
717 {
718 if (x.x == 7)
719 break;
720 }
721 assert(Foo9068.destroyed == [5, 7]);
722 Foo9068.destroyed = null;
723 }
724
725 /***************************************/
726 // 11885
727
728 struct Foo11885
729 {
730 static int[] destroyed;
731 int x;
~thisFoo11885732 ~this() { destroyed ~= x; }
733 }
734
735 struct SimpleCounter11885
736 {
737 static int destroyedCount;
738 enum int limit = 5;
739 int counter;
~this()740 ~this() { destroyedCount++; }
741
742 // Range primitives.
empty()743 @property bool empty() const { return counter >= limit; }
front()744 @property int front() { return counter; }
popFront()745 void popFront() { counter++; }
746 }
747
test11885()748 void test11885()
749 {
750 //----------------------------------------
751 // There was never a bug in this case (no range).
752 int sum;
753 loop_simple:
754 foreach (i; [10, 20])
755 {
756 sum += i;
757 continue loop_simple;
758 }
759 assert(sum == 30);
760
761 //----------------------------------------
762 // There was a bug with loops over ranges.
763 int last = -1;
764 X: foreach (i; SimpleCounter11885())
765 {
766 switch(i)
767 {
768 case 3:
769 continue X;
770 default:
771 last = i;
772 }
773 }
774 assert(last == 4);
775 assert(SimpleCounter11885.destroyedCount == 1);
776
777 //----------------------------------------
778 // Simpler case: the compiler error had nothing to do with the switch.
779 last = -1;
780 loop_with_range:
781 foreach (i; SimpleCounter11885())
782 {
783 last = i;
784 continue loop_with_range;
785 }
786 assert(last == 4);
787 assert(SimpleCounter11885.destroyedCount == 2);
788
789 //----------------------------------------
790 // Test with destructors: the loop is implicitly wrapped into two
791 // try/finally clauses.
792 loop_with_dtors:
793 for (auto x = Foo11885(4), y = Foo11885(5); x.x != 10; ++x.x)
794 {
795 if (x.x == 8)
796 continue loop_with_dtors;
797 }
798 assert(Foo11885.destroyed == [5, 10]);
799 Foo11885.destroyed = null;
800
801 //----------------------------------------
802 // Same with an unlabelled continue.
803 for (auto x = Foo11885(4), y = Foo11885(5); x.x != 10; ++x.x)
804 {
805 if (x.x == 7)
806 continue;
807 }
808 assert(Foo11885.destroyed == [5, 10]);
809 Foo11885.destroyed = null;
810 }
811
812 /***************************************/
813 // 10475
814
test10475a()815 void test10475a()
816 {
817 struct DirIterator
818 {
819 int _store = 42;
820 ~this() { assert(0); }
821 }
822
823 DirIterator dirEntries()
824 {
825 throw new Exception("");
826 }
827
828 try
829 {
830 for (DirIterator c = dirEntries(); true; ) {}
831 assert(0);
832 }
833 catch (Exception e)
834 {
835 assert(e.next is null);
836 }
837 }
838
test10475b()839 void test10475b()
840 {
841 uint g;
842 struct S
843 {
844 uint flag;
845 ~this() { g |= flag; }
846 }
847
848 S thrown()
849 {
850 throw new Exception("");
851 }
852
853 g = 0x0;
854 try
855 {
856 for (auto x = S(0x1), y = S(0x2), z = thrown(); true; ) {}
857 assert(0);
858 }
859 catch (Exception e)
860 {
861 assert(e.next is null);
862 }
863 assert(g == 0x3);
864
865 g = 0x0;
866 try
867 {
868 for (auto x = S(0x1), y = thrown(), z = S(0x2); true; ) {}
869 assert(0);
870 }
871 catch (Exception e)
872 {
873 assert(e.next is null);
874 }
875 assert(g == 0x1);
876
877 g = 0x0;
878 try
879 {
880 for (auto x = thrown(), y = S(0x1), z = S(0x2); true; ) {}
881 assert(0);
882 }
883 catch (Exception e)
884 {
885 assert(e.next is null);
886 }
887 assert(g == 0x0);
888 }
889
890 /***************************************/
891 // 11291
892
test11291()893 void test11291()
894 {
895 struct Tuple(T...)
896 {
897 T field;
898 alias field this;
899 }
900 struct zip
901 {
902 string[] s1, s2;
903
904 bool empty() { return true; }
905 auto front() { return Tuple!(string, string)(s1[0], s2[0]); }
906 void popFront() {}
907 }
908
909 foreach (const a, const b; zip(["foo"], ["bar"]))
910 {
911 static assert(is(typeof(a) == const string));
912 static assert(is(typeof(b) == const string));
913
914 static assert(!__traits(compiles, a = "something"));
915 static assert(!__traits(compiles, b = "something"));
916 }
917 }
918
919 /***************************************/
920 // 12103
921
922 alias TypeTuple12103(TL...) = TL;
923
924 alias Id12103(alias a) = a;
925
test12103()926 void test12103()
927 {
928 alias fs1 = TypeTuple12103!(() => 0, () => 1);
929 foreach (i, f; fs1)
930 {
931 static assert(f() == i);
932 static assert(Id12103!f() == i);
933 assert(f() == i);
934 assert(Id12103!f() == i);
935 }
936
937 alias fs2 = TypeTuple12103!(x=>x+0, y=>y+1);
938 foreach (i, f; fs2)
939 {
940 static assert(f(0) == i);
941 static assert(Id12103!f(0) == i);
942 assert(f(0) == i);
943 assert(Id12103!f(0) == i);
944 }
945 }
946
947 /***************************************/
948 // 12739
949
950 struct S12739
951 {
952 nothrow:
opApplyS12739953 int opApply(int delegate(ref int) nothrow dg)
954 {
955 return 0;
956 }
957 }
958
test12739()959 void test12739() nothrow
960 {
961 S12739 s;
962 foreach (e; s) {}
963 }
964
965 /***************************************/
966 // 12932
967
test12932()968 void test12932() @nogc
969 {
970 int sum;
971 foreach (e; [1,2,3])
972 {
973 sum += e;
974 }
975 assert(sum == 6);
976 }
977
978 /***************************************/
979 // 13756
980
test13756()981 void test13756()
982 {
983 printf("test13756()\n");
984 int[int] org = [1:2], aa;
985
986 aa = org.dup;
987 foreach (v; aa)
988 {
989 static assert(is(typeof(v) == int));
990 v = 20;
991 }
992 assert(aa == [1:2]);
993
994 aa = org.dup;
995 foreach (ref v; aa)
996 {
997 static assert(is(typeof(v) == int));
998 v = 20;
999 }
1000 assert(aa == [1:20]);
1001
1002 aa = org.dup;
1003 foreach (k, v; aa)
1004 {
1005 static assert(is(typeof(k) == int));
1006 static assert(is(typeof(v) == int));
1007 k = 10;
1008 v = 20;
1009 }
1010 assert(aa == [1:2]);
1011
1012 aa = org.dup;
1013 foreach (k, ref v; aa)
1014 {
1015 static assert(is(typeof(k) == int));
1016 static assert(is(typeof(v) == int));
1017 k = 10;
1018 v = 20;
1019 }
1020 assert(aa == [1:20]);
1021
1022 aa = org.dup;
1023 foreach (ref k, v; aa) // NG -> OK
1024 {
1025 static assert(is(typeof(k) == const int));
1026 static assert(is(typeof(v) == int));
1027 static assert(!__traits(compiles, k = 10));
1028 v = 20;
1029 }
1030 assert(aa == [1:2]);
1031
1032 aa = org.dup;
1033 foreach (ref k, ref v; aa) // NG -> OK
1034 {
1035 static assert(is(typeof(k) == const int));
1036 static assert(is(typeof(v) == int));
1037 static assert(!__traits(compiles, k = 10));
1038 v = 20;
1039 }
1040 assert(aa == [1:20]);
1041
1042 foreach (ref const k, v; aa) // NG -> OK, same with 'ref k'
1043 {
1044 static assert(is(typeof(k) == const int));
1045 }
1046 }
1047
1048 /***************************************/
1049 // 14653
1050
1051 static string result14653;
1052
1053 class RangeClass14653
1054 {
1055 int a;
1056
this(T)1057 this(T)(T...) { result14653 ~= "c"; }
~this()1058 ~this() { result14653 ~= "d"; a = -1; }
1059
empty()1060 @property bool empty() { result14653 ~= "e"; return a >= 2; }
front()1061 @property int front() { result14653 ~= "f"; assert(a >= 0); return a; }
popFront()1062 void popFront() { result14653 ~= "p"; ++a; }
1063 }
1064
scoped14653(T,A...)1065 auto scoped14653(T, A...)(A args)
1066 {
1067 static struct Scoped(T)
1068 {
1069 void[__traits(classInstanceSize, T)] store;
1070 T payload() { return cast(T)cast(void*)store.ptr; }
1071 alias payload this;
1072
1073 ~this()
1074 {
1075 //.destroy(payload);
1076 payload.__dtor();
1077 (cast(byte[])store)[] = 0;
1078 }
1079 }
1080
1081 Scoped!T result = void;
1082
1083 //emplace!T(result.store[], args);
1084 result.store[] = typeid(T).initializer[];
1085 result.payload.__ctor(args);
1086
1087 return result;
1088 }
1089
test14653()1090 void test14653()
1091 {
1092 printf("test14653()\n");
1093 foreach (e; scoped14653!RangeClass14653(1))
1094 {
1095 result14653 ~= "b";
1096 }
1097 assert(result14653 == "cefbpefbped", result14653);
1098 }
1099
1100 /***************************************/
1101
main()1102 int main()
1103 {
1104 test1();
1105 test2411();
1106 test2442();
1107 test2443();
1108 test3187();
1109 test4090a();
1110 test4090b();
1111 test5605();
1112 test7004();
1113 test10221();
1114 test7406();
1115 test6659();
1116 test6659a();
1117 test6659b();
1118 test6659c();
1119 test7814();
1120 test6652();
1121 test9068();
1122 test11885();
1123 test10475a();
1124 test10475b();
1125 test11291();
1126 test12103();
1127 test12739();
1128 printf("test12932()\n");
1129 test12932();
1130 test13756();
1131 test14653();
1132
1133 printf("Success\n");
1134 return 0;
1135 }
1136