1 import core.stdc.stdio;
2
TypeTuple(T...)3 template TypeTuple(T...){ alias T TypeTuple; }
4
5 /***************************************************/
6 // 2625
7
8 struct Pair {
9 immutable uint g1;
10 uint g2;
11 }
12
test1()13 void test1() {
14 Pair[1] stuff;
15 static assert(!__traits(compiles, (stuff[0] = Pair(1, 2))));
16 }
17
18 /***************************************************/
19 // 5327
20
21 struct ID
22 {
23 immutable int value;
24 }
25
26 struct Data
27 {
28 ID id;
29 }
test2()30 void test2()
31 {
32 Data data = Data(ID(1));
33 immutable int* val = &data.id.value;
34 static assert(!__traits(compiles, data = Data(ID(2))));
35 }
36
37 /***************************************************/
38
39 struct S31A
40 {
41 union
42 {
43 immutable int field1;
44 immutable int field2;
45 }
46
47 enum result = false;
48 }
49 struct S31B
50 {
51 union
52 {
53 immutable int field1;
54 int field2;
55 }
56
57 enum result = true;
58 }
59 struct S31C
60 {
61 union
62 {
63 int field1;
64 immutable int field2;
65 }
66
67 enum result = true;
68 }
69 struct S31D
70 {
71 union
72 {
73 int field1;
74 int field2;
75 }
76
77 enum result = true;
78 }
79
80 struct S32A
81 {
82 int dummy0;
83 union
84 {
85 immutable int field1;
86 int field2;
87 }
88
89 enum result = true;
90 }
91 struct S32B
92 {
93 immutable int dummy0;
94 union
95 {
96 immutable int field1;
97 int field2;
98 }
99
100 enum result = false;
101 }
102
103
104 struct S32C
105 {
106 union
107 {
108 immutable int field1;
109 int field2;
110 }
111 int dummy1;
112
113 enum result = true;
114 }
115 struct S32D
116 {
117 union
118 {
119 immutable int field1;
120 int field2;
121 }
122 immutable int dummy1;
123
124 enum result = false;
125 }
126
test3()127 void test3()
128 {
129 foreach (S; TypeTuple!(S31A,S31B,S31C,S31D, S32A,S32B,S32C,S32D))
130 {
131 S s;
132 static assert(__traits(compiles, s = s) == S.result);
133 }
134 }
135
136 /***************************************************/
137 // 3511
138
139 struct S4
140 {
141 private int _prop = 42;
propertyS4142 ref int property() { return _prop; }
143 }
144
test4()145 void test4()
146 {
147 S4 s;
148 assert(s.property == 42);
149 s.property = 23; // Rewrite to s.property() = 23
150 assert(s.property == 23);
151 }
152
153 /***************************************************/
154
155 struct S5
156 {
157 int mX;
158 string mY;
159
xS5160 ref int x()
161 {
162 return mX;
163 }
yS5164 ref string y()
165 {
166 return mY;
167 }
168
errS5169 ref int err(Object)
170 {
171 static int v;
172 return v;
173 }
174 }
175
test5()176 void test5()
177 {
178 S5 s;
179 s.x += 4;
180 assert(s.mX == 4);
181 s.x -= 2;
182 assert(s.mX == 2);
183 s.x *= 4;
184 assert(s.mX == 8);
185 s.x /= 2;
186 assert(s.mX == 4);
187 s.x %= 3;
188 assert(s.mX == 1);
189 s.x <<= 3;
190 assert(s.mX == 8);
191 s.x >>= 1;
192 assert(s.mX == 4);
193 s.x >>>= 1;
194 assert(s.mX == 2);
195 s.x &= 0xF;
196 assert(s.mX == 0x2);
197 s.x |= 0x8;
198 assert(s.mX == 0xA);
199 s.x ^= 0xF;
200 assert(s.mX == 0x5);
201
202 s.x ^^= 2;
203 assert(s.mX == 25);
204
205 s.mY = "ABC";
206 s.y ~= "def";
207 assert(s.mY == "ABCdef");
208
209 static assert(!__traits(compiles, s.err += 1));
210 }
211
212 /***************************************************/
213 // 4424
214
test4424()215 void test4424()
216 {
217 static struct S
218 {
219 this(this) {}
220 void opAssign(T)(T rhs) if (!is(T == S)) {}
221 }
222 }
223
224 /***************************************************/
225 // 6174
226
227 struct CtorTest6174(Data)
228 {
229 const Data data;
230
231 const Data[2] sa1;
232 const Data[2][1] sa2;
233 const Data[][2] sa3;
234
235 const Data[] da1;
236 const Data[2][] da2;
237
238 this(Data a)
239 {
240 auto pdata = &data;
241
242 // If compiler can determine that an assignment really sets the fields
243 // which belongs to `this` object, it can bypass const qualifier.
244 // For example, sa3, da1, da2, and pdata have indirections.
245 // As long as you don't try to rewrite values beyond the indirections,
246 // an assignment will always be succeeded inside constructor.
247
248 static assert( is(typeof( data = a ))); // OK
249 static if (is(Data == struct))
250 {
251 static assert( is(typeof( data.x = 1 ))); // OK
252 static assert( is(typeof( data.y = 2 ))); // OK
253 }
254 static assert(!is(typeof( *pdata = a ))); // NG
255 static assert( is(typeof( *&data = a ))); // OK
256
257 static assert( is(typeof( sa1 = [a,a] ))); // OK
258 static assert( is(typeof( sa1[0] = a ))); // OK
259 static assert( is(typeof( sa1[] = a ))); // OK
260 static assert( is(typeof( sa1[][] = a ))); // OK
261
262 static assert( is(typeof( sa2 = [[a,a]] ))); // OK
263 static assert( is(typeof( sa2[0][0] = a ))); // OK
264 static assert( is(typeof( sa2[][0][] = a ))); // OK
265 static assert( is(typeof( sa2[0][][0] = a ))); // OK
266
267 static assert( is(typeof( sa3 = [[a],[]] ))); // OK
268 static assert( is(typeof( sa3[0] = [a,a] ))); // OK
269 static assert(!is(typeof( sa3[0][0] = a ))); // NG
270 static assert( is(typeof( sa3[] = [a] ))); // OK
271 static assert( is(typeof( sa3[][0] = [a] ))); // OK
272 static assert(!is(typeof( sa3[][0][0] = a ))); // NG
273
274 static assert( is(typeof( da1 = [a,a] ))); // OK
275 static assert(!is(typeof( da1[0] = a ))); // NG
276 static assert(!is(typeof( da1[] = a ))); // NG
277
278 static assert( is(typeof( da2 = [[a,a]] ))); // OK
279 static assert(!is(typeof( da2[0][0] = a ))); // NG
280 static assert(!is(typeof( da2[] = [a,a] ))); // NG
281 static assert(!is(typeof( da2[][0] = a ))); // NG
282 static assert(!is(typeof( da2[0][] = a ))); // NG
283 }
284 void func(Data a)
285 {
286 auto pdata = &data;
287
288 static assert(!is(typeof( data = a ))); // NG
289 static if (is(Data == struct))
290 {
291 static assert(!is(typeof( data.x = 1 ))); // NG
292 static assert(!is(typeof( data.y = 2 ))); // NG
293 }
294 static assert(!is(typeof( *pdata = a ))); // NG
295 static assert(!is(typeof( *&data = a ))); // NG
296
297 static assert(!is(typeof( sa1 = [a,a] ))); // NG
298 static assert(!is(typeof( sa1[0] = a ))); // NG
299 static assert(!is(typeof( sa1[] = a ))); // NG
300 static assert(!is(typeof( sa1[][] = a ))); // NG
301
302 static assert(!is(typeof( sa2 = [[a,a]] ))); // NG
303 static assert(!is(typeof( sa2[0][0] = a ))); // NG
304 static assert(!is(typeof( sa2[][0][] = a ))); // NG
305 static assert(!is(typeof( sa2[0][][0] = a ))); // NG
306
307 static assert(!is(typeof( sa3 = [[a],[]] ))); // NG
308 static assert(!is(typeof( sa3[0] = [a,a] ))); // NG
309 static assert(!is(typeof( sa3[0][0] = a ))); // NG
310 static assert(!is(typeof( sa3[] = [a] ))); // NG
311 static assert(!is(typeof( sa3[][0] = [a] ))); // NG
312 static assert(!is(typeof( sa3[][0][0] = a ))); // NG
313
314 static assert(!is(typeof( da1 = [a,a] ))); // NG
315 static assert(!is(typeof( da1[0] = a ))); // NG
316 static assert(!is(typeof( da1[] = a ))); // NG
317
318 static assert(!is(typeof( da2 = [[a,a]] ))); // NG
319 static assert(!is(typeof( da2[0][0] = a ))); // NG
320 static assert(!is(typeof( da2[] = [a,a] ))); // NG
321 static assert(!is(typeof( da2[][0] = a ))); // NG
322 static assert(!is(typeof( da2[0][] = a ))); // NG
323 }
324 }
325
326 const char gc6174;
327 const char[1] ga6174;
328 static this()
329 {
330 gc6174 = 'a'; // OK
331 ga6174[0] = 'a'; // line 5, Err
332 }
333 struct Foo6174
334 {
335 const char cc;
336 const char[1] array;
337 const char[1] arr;
338 this(char c)
339 {
340 cc = c; // OK
341 array = [c]; // line 12, Err
342 arr[0] = c; // line 12, Err
343 }
344 }
345 void test6174a()
346 {
347 static struct Pair
348 {
349 const int x;
350 int y;
351 }
352 alias CtorTest6174!long CtorTest1;
353 alias CtorTest6174!Pair CtorTest2;
354
355 auto foo = Foo6174('c');
356 }
357
358 /***************************************************/
359
360 template Select(bool cond, T, F)
361 {
362 static if (cond)
363 alias Select = T;
364 else
365 alias Select = F;
366 }
367
368 void test6174b()
369 {
370 enum { none, unrelated, mutable, constant }
371
372 static struct FieldStruct(bool c, int k)
373 {
374 enum fieldConst = c;
375 enum assignKind = k;
376
377 Select!(fieldConst, const int, int) x;
378 int y;
379
380 static if (assignKind == none) {}
381 static if (assignKind == unrelated) void opAssign(int) {}
382 static if (assignKind == mutable) void opAssign(FieldStruct) {}
383 static if (assignKind == constant) void opAssign(FieldStruct) const {}
384 }
385 static struct TestStruct(F, bool fieldConst)
386 {
387 int w;
388 Select!(fieldConst, const F, F) f;
389 Select!(fieldConst, const int, int) z;
390
391 this(int)
392 {
393 // If F has an identity `opAssign`,it is used even for initializing.
394 // Otherwise, initializing will always succeed, by bypassing const qualifier.
395 static assert(is(typeof( f = F() )) == (
396 F.assignKind == none ||
397 F.assignKind == unrelated ||
398 F.assignKind == mutable ||
399 F.assignKind == constant));
400
401 static assert(is(typeof( w = 1000 )) == true);
402 static assert(is(typeof( f.x = 1000 )) == true);
403 static assert(is(typeof( f.y = 1000 )) == true);
404 static assert(is(typeof( z = 1000 )) == true);
405 }
406 void func()
407 {
408 // In mutable member functions, identity assignment is allowed
409 // when all of the fields are identity assignable,
410 // or identity `opAssign`, which callable from mutable object, is defined.
411 static assert(__traits(compiles, f = F()) == (
412 F.assignKind == none && !fieldConst && !F.fieldConst ||
413 F.assignKind == unrelated && !fieldConst && !F.fieldConst ||
414 F.assignKind == constant ||
415 F.assignKind == mutable && !fieldConst));
416
417 static assert(__traits(compiles, w = 1000) == true);
418 static assert(__traits(compiles, f.x = 1000) == (!fieldConst && !F.fieldConst));
419 static assert(__traits(compiles, f.y = 1000) == (!fieldConst && true ));
420 static assert(__traits(compiles, z = 1000) == !fieldConst);
421 }
422 void func() const
423 {
424 // In non-mutable member functions, identity assignment is allowed
425 // just only user-defined identity `opAssign` is qualified.
426 static assert(__traits(compiles, f = F()) == (F.assignKind == constant));
427
428 static assert(__traits(compiles, w = 1000) == false);
429 static assert(__traits(compiles, f.x = 1000) == false);
430 static assert(__traits(compiles, f.y = 1000) == false);
431 static assert(__traits(compiles, z = 1000) == false);
432 }
433 }
434 foreach (fieldConst; TypeTuple!(false, true))
435 foreach ( hasConst; TypeTuple!(false, true))
436 foreach (assignKind; TypeTuple!(none, unrelated, mutable, constant))
437 {
438 alias TestStruct!(FieldStruct!(hasConst, assignKind), fieldConst) TestX;
439 }
440 }
441
442 void test6174c()
443 {
444 static assert(!is(typeof({
445 int func1a(int n)
446 in{ n = 10; }
447 body { return n; }
448 })));
449 static assert(!is(typeof({
450 int func1b(int n)
451 out(r){ r = 20; }
452 body{ return n; }
453 })));
454
455 struct DataX
456 {
457 int x;
458 }
459 static assert(!is(typeof({
460 DataX func2a(DataX n)
461 in{ n.x = 10; }
462 body { return n; }
463 })));
464 static assert(!is(typeof({
465 DataX func2b(DataX n)
466 in{}
467 out(r){ r.x = 20; }
468 body{ return n; }
469 })));
470 }
471
472 /***************************************************/
473 // 6216
474
475 void test6216a()
476 {
477 static class C{}
478
479 static struct Xa{ int n; }
480 static struct Xb{ int[] a; }
481 static struct Xc{ C c; }
482 static struct Xd{ void opAssign(typeof(this) rhs){} }
483 static struct Xe{ void opAssign(T)(T rhs){} }
484 static struct Xf{ void opAssign(int rhs){} }
485 static struct Xg{ void opAssign(T)(T rhs)if(!is(T==typeof(this))){} }
486
487 // has value type as member
488 static struct S1 (X){ static if (!is(X==void)) X x; int n; }
489
490 // has reference type as member
491 static struct S2a(X){ static if (!is(X==void)) X x; int[] a; }
492 static struct S2b(X){ static if (!is(X==void)) X x; C c; }
493
494 // has identity opAssign
495 static struct S3a(X){ static if (!is(X==void)) X x; void opAssign(typeof(this) rhs){} }
496 static struct S3b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs){} }
497
498 // has non identity opAssign
499 static struct S4a(X){ static if (!is(X==void)) X x; void opAssign(int rhs){} }
500 static struct S4b(X){ static if (!is(X==void)) X x; void opAssign(T)(T rhs)if(!is(T==typeof(this))){} }
501
502 enum result = [
503 /*S1, S2a, S2b, S3a, S3b, S4a, S4b*/
504 /*- */ [true, true, true, true, true, true, true],
505 /*Xa*/ [true, true, true, true, true, true, true],
506 /*Xb*/ [true, true, true, true, true, true, true],
507 /*Xc*/ [true, true, true, true, true, true, true],
508 /*Xd*/ [true, true, true, true, true, true, true],
509 /*Xe*/ [true, true, true, true, true, true, true],
510 /*Xf*/ [true, true, true, true, true, true, true],
511 /*Xg*/ [true, true, true, true, true, true, true],
512 ];
513
514 pragma(msg, "\\\tS1\tS2a\tS2b\tS3a\tS3b\tS4a\tS4b");
515 foreach (i, X; TypeTuple!(void,Xa,Xb,Xc,Xd,Xe,Xf,Xg))
516 {
517 S1!X s1;
518 S2a!X s2a;
519 S2b!X s2b;
520 S3a!X s3a;
521 S3b!X s3b;
522 S4a!X s4a;
523 S4b!X s4b;
524
525 pragma(msg,
526 is(X==void) ? "-" : X.stringof,
527 "\t", __traits(compiles, (s1 = s1)),
528 "\t", __traits(compiles, (s2a = s2a)),
529 "\t", __traits(compiles, (s2b = s2b)),
530 "\t", __traits(compiles, (s3a = s3a)),
531 "\t", __traits(compiles, (s3b = s3b)),
532 "\t", __traits(compiles, (s4a = s4a)),
533 "\t", __traits(compiles, (s4b = s4b)) );
534
535 static assert(result[i] ==
536 [ __traits(compiles, (s1 = s1)),
537 __traits(compiles, (s2a = s2a)),
538 __traits(compiles, (s2b = s2b)),
539 __traits(compiles, (s3a = s3a)),
540 __traits(compiles, (s3b = s3b)),
541 __traits(compiles, (s4a = s4a)),
542 __traits(compiles, (s4b = s4b)) ]);
543 }
544 }
545
546 void test6216b()
547 {
548 static int cnt = 0;
549
550 static struct X
551 {
552 int n;
553 void opAssign(X rhs){ cnt = 1; }
554 }
555 static struct S
556 {
557 int n;
558 X x;
559 }
560
561 S s;
562 s = s;
563 assert(cnt == 1);
564 // Built-in opAssign runs member's opAssign
565 }
566
567 void test6216c()
568 {
569 static int cnt = 0;
570
571 static struct X
572 {
573 int n;
574 void opAssign(const X rhs) const { cnt = 2; }
575 }
576 static struct S
577 {
578 int n;
579 const(X) x;
580 }
581
582 S s;
583 const(S) cs;
584 s = s;
585 s = cs; // cs is copied as mutable and assigned into s
586 assert(cnt == 2);
587 static assert(!__traits(compiles, cs = cs));
588 // built-in opAssin is only allowed with mutable object
589 }
590
591 void test6216d()
592 {
593 static int cnt = 0;
594
595 static struct X
596 {
597 int[] arr; // X has mutable indirection
598 void opAssign(const X rhs) const { ++cnt; }
599 }
600 static struct S
601 {
602 int n;
603 const(X) x;
604 }
605
606 X mx;
607 const X cx;
608 mx = mx; // copying mx to const X is possible
609 assert(cnt == 1);
610 mx = cx;
611 assert(cnt == 2);
612 cx = mx; // copying mx to const X is possible
613 assert(cnt == 3);
614
615 S s;
616 const(S) cs;
617 s = s;
618 s = cs;
619 //assert(cnt == 4);
620 static assert(!__traits(compiles, cs = cs));
621 // built-in opAssin is only allowed with mutable object
622 }
623
624 void test6216e()
625 {
626 static struct X
627 {
628 int x;
629 @disable void opAssign(X);
630 }
631 static struct S
632 {
633 X x;
634 }
635 S s;
636 static assert(!__traits(compiles, s = s));
637 // built-in generated opAssin is marked as @disable.
638 }
639
640 /***************************************************/
641 // 6286
642
643 void test6286()
644 {
645 const(int)[4] src = [1, 2, 3, 4];
646 int[4] dst;
647 dst = src;
648 dst[] = src[];
649 dst = 4;
650 int[4][4] x;
651 x = dst;
652 }
653
654 /***************************************************/
655 // 6336
656
657 void test6336()
658 {
659 // structs aren't identity assignable
660 static struct S1
661 {
662 immutable int n;
663 }
664 static struct S2
665 {
666 void opAssign(int n){ assert(0); }
667 }
668
669 S1 s1;
670 S2 s2;
671
672 void f(S)(out S s){}
673 static assert(!__traits(compiles, f(s1)));
674 f(s2);
675 // Out parameters refuse only S1 because it isn't blit assignable
676
677 ref S g(S)(ref S s){ return s; }
678 g(s1);
679 g(s2);
680 // Allow return by ref both S1 and S2
681 }
682
683 /***************************************************/
684 // 8783
685
686 struct Foo8783
687 {
688 int[1] bar;
689 }
690
691 const Foo8783[1] foos8783;
692
693 static this()
694 {
695 foreach (i; 0 .. foos8783.length)
696 foos8783[i].bar[i] = 1; // OK
697 foreach (i, ref f; foos8783)
698 f.bar[i] = 1; // line 9, Error
699 }
700
701 /***************************************************/
702 // 9077
703
704 struct S9077a
705 {
706 void opAssign(int n) {}
707 void test() { typeof(this) s; s = this; }
708 this(this) {}
709 }
710 struct S9077b
711 {
712 void opAssign()(int n) {}
713 void test() { typeof(this) s; s = this; }
714 this(this) {}
715 }
716
717 /***************************************************/
718 // 9140
719
720 immutable(int)[] bar9140()
721 out(result) {
722 foreach (ref r; result) {}
723 } body {
724 return null;
725 }
726
727 /***************************************************/
728 // 9154
729
730 struct S9154a
731 {
732 int x;
733 void opAssign(ref S9154a s) { }
734 }
735 struct S9154b
736 {
737 int x;
738 void opAssign(X)(ref X s) { }
739 }
740 struct T9154
741 {
742 S9154a member1;
743 S9154b member2;
744 }
745
746 void test9154()
747 {
748 T9154 t1, t2;
749 t1 = t2;
750 }
751
752 /***************************************************/
753 // 9258
754
755 class A9258 {}
756 class B9258 : A9258 // Error: class test.B9258 identity assignment operator overload is illegal
757 {
758 void opAssign(A9258 b) {}
759 }
760
761 class C9258
762 {
763 int n;
764 alias n this;
765 void opAssign(int n) {}
766 }
767 class D9258
768 {
769 int n;
770 alias n this;
771 void opAssign(int n, int y = 0) {}
772 }
773 class E9258 : A9258
774 {
775 void set(A9258 a) {}
776 alias set opAssign;
777 }
778
779 /***************************************************/
780 // 9416
781
782 struct S9416
783 {
784 void opAssign()(S9416)
785 {
786 static assert(0);
787 }
788 }
789 struct U9416
790 {
791 S9416 s;
792 }
793 void test9416()
794 {
795 U9416 u;
796 static assert(__traits(allMembers, U9416)[$-1] == "opAssign");
797 static assert(!__traits(compiles, u = u));
798 }
799
800 /***************************************************/
801 // 9658
802
803 struct S9658
804 {
805 private bool _isNull = true;
806 this(int v) const
807 {
808 _isNull = false; // cannot modify const expression this._isNull
809 }
810 }
811
812 /***************************************************/
813 // 11187
814
815 void test11187()
816 {
817 static struct X
818 {
819 int[] arr;
820 }
821 static struct S
822 {
823 const(X) cx;
824 }
825 static assert(is(typeof((const S).init.cx.arr) == const(int[])));
826 static assert(is(typeof(( S).init.cx.arr) == const(int[])));
827 const S sc;
828 S sm = sc;
829 static assert(is(const S : S));
830 }
831
832 /***************************************************/
833 // 12131
834
835 struct X12131
836 {
837 void opAssign()(X12131 y) pure {}
838 }
839
840 struct Y12131
841 {
842 X12131 a;
843 }
844
845 void test12131() pure
846 {
847 X12131 x;
848 x = X12131(); // OK
849
850 Y12131 y;
851 y = Y12131(); // OK <- Error
852 }
853
854 /***************************************************/
855 // 12211
856
857 void test12211()
858 {
859 int a = 0;
860 void foo(ref int x)
861 {
862 assert(x == 10);
863 assert(&x == &a);
864 x = 3;
865 }
866 foo(a = 10);
867 assert(a == 3);
868 foo(a += 7);
869 assert(a == 3);
870
871 // array ops should make rvalue
872 int[3] sa, sb;
873 void bar(ref int[]) {}
874 static assert(!__traits(compiles, bar(sa[] = sb[])));
875 static assert(!__traits(compiles, bar(sa[] += sb[])));
876 }
877
878 /***************************************************/
879 // 4791 (dup of 12212)
880
881 void test4791()
882 {
883 int[2] na;
884 na = na;
885
886 static struct S
887 {
888 static string res;
889 int n;
890 this(this) { ++n; res ~= "p" ~ cast(char)('0' + n); }
891 ~this() { res ~= "d" ~ cast(char)('0' + n); }
892 }
893 {
894 S[3] sa;
895 sa[0].n = 1, sa[1].n = 2, sa[2].n = 3;
896
897 S.res = null;
898 sa = sa;
899 assert(S.res == "p2d1p3d2p4d3");
900 assert(sa[0].n == 2 && sa[1].n == 3 && sa[2].n == 4);
901
902 S.res = null;
903 }
904 assert(S.res == "d4d3d2");
905 }
906
907 /***************************************************/
908 // 12212
909
910 void test12212()
911 {
912 struct S
913 {
914 int x, y;
915 static int cpctor;
916 this(this) { cpctor++; }
917 }
918
919 void funcVal(E)(E[3] x) {}
920 auto funcRef(E)(ref E[3] x) { return &x; }
921 ref get(E)(ref E[3] a){ return a; }
922
923 {
924 int[3] a, b;
925 funcVal(a = b);
926
927 auto p = funcRef(a = b);
928 assert(p == &a);
929 }
930
931 {
932 S.cpctor = 0;
933
934 S[3] a, b;
935 assert(S.cpctor == 0);
936
937 S[3] c = a;
938 //printf("cpctpr = %d\n", S.cpctor);
939 assert(S.cpctor == 3);
940 S.cpctor = 0;
941
942 c = a;
943 //printf("cpctpr = %d\n", S.cpctor);
944 assert(S.cpctor == 3);
945 S.cpctor = 0;
946
947 c = (a = b);
948 //printf("cpctpr = %d\n", S.cpctor);
949 assert(S.cpctor == 6);
950 S.cpctor = 0;
951
952 c = (get(a) = b);
953 //printf("cpctpr = %d\n", S.cpctor);
954 assert(S.cpctor == 6);
955 S.cpctor = 0;
956 }
957 {
958 S.cpctor = 0;
959
960 S[3] a, b;
961 assert(S.cpctor == 0);
962
963 funcVal(a = b);
964 //printf("cpctpr = %d\n", S.cpctor);
965 assert(S.cpctor == 6);
966 S.cpctor = 0;
967
968 funcVal(get(a) = b);
969 //printf("cpctpr = %d\n", S.cpctor);
970 assert(S.cpctor == 6);
971 S.cpctor = 0;
972 }
973 {
974 S.cpctor = 0;
975
976 S[3] a, b;
977 assert(S.cpctor == 0);
978
979 S[3]* p;
980
981 p = funcRef(a = b);
982 //printf("cpctpr = %d\n", S.cpctor);
983 assert(p == &a);
984 assert(S.cpctor == 3);
985 S.cpctor = 0;
986
987 p = funcRef(get(a) = b);
988 assert(p == &a);
989 //printf("cpctpr = %d\n", S.cpctor);
990 assert(S.cpctor == 3);
991 S.cpctor = 0;
992 }
993 }
994
995 /***************************************************/
996 // 12650
997
998 void test12650()
999 {
1000 // AssignExp::toElem should make an lvalue of e1.
1001 static class A1
1002 {
1003 struct S { int a; }
1004
1005 static foo(ref const(S) s)
1006 {
1007 assert(s.a == 2);
1008 return &s;
1009 }
1010
1011 S s;
1012
1013 this()
1014 {
1015 const v = S(2);
1016
1017 // (this.s = v) will become ConstructExp
1018 auto p = foo(s = v);
1019 assert(p == &s);
1020 }
1021 }
1022 assert(new A1().s.a == 2);
1023
1024 static class A2
1025 {
1026 static foo(ref int[2] sa)
1027 {
1028 assert(sa[1] == 2);
1029 return &sa;
1030 }
1031
1032 int[2] sa;
1033
1034 this()
1035 {
1036 // (this.sa = [1,2]) will become ConstructExp
1037 auto p = foo(sa = [1,2]);
1038 assert(p == &sa);
1039 }
1040 }
1041 assert(new A2().sa[1] == 2);
1042
1043 static class A3
1044 {
1045 static foo(ref int n)
1046 {
1047 assert(n == 2);
1048 return &n;
1049 }
1050
1051 int n;
1052
1053 this()
1054 {
1055 const v = 2;
1056
1057 // (this.n = v) will become ConstructExp
1058 auto p = foo(n = v);
1059 assert(p == &n);
1060 }
1061 }
1062 assert(new A3().n == 2);
1063 }
1064
1065 /***************************************************/
1066 // 13044
1067
1068 void test13044()
1069 {
1070 static struct Good
1071 {
1072 const int i;
1073 }
1074
1075 static struct Bad
1076 {
1077 const int i;
1078 ~this() {}
1079 }
1080
1081 Good good1, good2;
1082 static assert(!__traits(compiles, { good1 = good2; })); // OK
1083
1084 Bad bad1, bad2;
1085 static assert(!__traits(compiles, { bad1 = bad2; })); // OK <- fails
1086 }
1087
1088 /***************************************************/
1089 // 12500
1090
1091 void test12500()
1092 {
1093 size_t foo;
1094 ++foo *= 1.5; // Rewrite to: (foo += 1) *= 1.5;
1095 }
1096
1097 /***************************************************/
1098 // 14672
1099
1100 void test14672()
1101 {
1102 interface I {}
1103
1104 class B {}
1105 class D : B, I {}
1106
1107 D d = new D();
1108 D[] da = [d];
1109 B[] ba = [null];
1110 I[] ia = [null];
1111
1112 // ba and da points different payloads,
1113 // so element-wise assignment should work.
1114 ba[] = da[]; // OK <- e2ir ICE
1115 assert(ba[0] is d);
1116
1117 // Today element-wise assignment is implemented as memcpy, For that reason
1118 // the conversion from derived classes to base interfaces is disallowed
1119 // because it requries offset adjustments.
1120 static assert(!__traits(compiles, { ia[] = da[]; }));
1121
1122 // after the assignment, ba will wongly point the payload of da,
1123 // that's typed as D[]. To aboid type system breaking, it's disallowed.
1124 static assert(!__traits(compiles, { ba = da; }));
1125
1126 // the assigned array literal is a new payload,
1127 // so rebinding ba should work.
1128 ba = [d]; // OK
1129 assert(ba[0] is d);
1130 }
1131
1132 /***************************************************/
1133 // 15044
1134
1135 void destroy15044(T)(ref T obj)
1136 {
1137 static if (__traits(hasMember, T, "__xdtor"))
1138 obj.__xdtor();
1139 else
1140 static assert(0, T.stringof);
1141 }
1142
1143 struct V15044
1144 {
1145 ~this()
1146 {
1147 }
1148
1149 RC15044!V15044 dup()
1150 {
1151 return RC15044!V15044(&this);
1152 }
1153 }
1154
1155 struct RC15044(T)
1156 {
1157 ~this()
1158 {
1159 destroy15044(*t);
1160 static assert(__traits(hasMember, T, "__xdtor"));
1161 }
1162 T* t;
1163 }
1164
1165 /***************************************************/
1166
1167 int main()
1168 {
1169 test1();
1170 test2();
1171 test3();
1172 test4();
1173 test5();
1174 test4424();
1175 test6174a();
1176 test6174b();
1177 test6174c();
1178 test6216a();
1179 test6216b();
1180 test6216c();
1181 test6216d();
1182 test6216e();
1183 test6286();
1184 test6336();
1185 test9154();
1186 test9416();
1187 test11187();
1188 test12131();
1189 test12211();
1190 test4791();
1191 test12212();
1192 test12650();
1193 test13044();
1194 test12500();
1195 test14672();
1196
1197 printf("Success\n");
1198 return 0;
1199 }
1200