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