1 // PERMUTE_ARGS:
2 
3 // MT!"y" is analyzed from the pragma inside MT!"x"
4 /*
5 TEST_OUTPUT:
6 ---
7 CT x.offsetof = <
8 CT y.offsetof = <
9 0 > y
10 0 > x
11 ---
12 */
13 
MT(string id)14 mixin template MT(string id)
15 {
16     union
17     {
18         mixin("void* " ~ id ~ ";");
19     }
20 
21     // Evaluating `typeof(this).init` completes data layout.
22     pragma(msg,
23         "CT " ~ id ~ ".offsetof = <\n",
24         cast(int)typeof(this).init.i.offsetof, " > " ~ id);
25 }
26 
27 struct S1
28 {
29     int i;
30     mixin MT!"x";
31     mixin MT!"y";
32 }
33 struct S2
34 {
35     int i;
36     union { void* x; }
37     union { void* y; }
38 }
39 struct S3
40 {
41     int i;
42     void* x;
43     void* y;
44 }
45 
main()46 void main()
47 {
48     // S1, S2, and S3 should have exactly same data layout.
49     static assert(S1.i.offsetof == S3.i.offsetof);
50     static assert(S1.i.offsetof == S3.i.offsetof);
51     static assert(S1.x.offsetof == S3.x.offsetof);
52     static assert(S1.y.offsetof == S3.y.offsetof);
53     static assert(S2.x.offsetof == S3.x.offsetof);
54     static assert(S2.y.offsetof == S3.y.offsetof);
55     static assert(S1.sizeof == S3.sizeof);
56     static assert(S2.sizeof == S3.sizeof);
57 
58     S1 s = void;
59 
60     s.i = 1;
61     assert(s.i == 1);
62     s.x = null;
63     assert(s.i == 1);
64     s.y = null;
65     assert(s.i == 1);
66 
67     char a, b;
68     s.x = cast(void*)&a;
69     assert(s.x is &a);
70     assert(s.y is null);
71     s.y = cast(void*)&b;
72     assert(s.x is &a);
73     assert(s.y is &b);
74 }
75