// PERMUTE_ARGS: // MT!"y" is analyzed from the pragma inside MT!"x" /* TEST_OUTPUT: --- CT x.offsetof = < CT y.offsetof = < 0 > y 0 > x --- */ mixin template MT(string id) { union { mixin("void* " ~ id ~ ";"); } // Evaluating `typeof(this).init` completes data layout. pragma(msg, "CT " ~ id ~ ".offsetof = <\n", cast(int)typeof(this).init.i.offsetof, " > " ~ id); } struct S1 { int i; mixin MT!"x"; mixin MT!"y"; } struct S2 { int i; union { void* x; } union { void* y; } } struct S3 { int i; void* x; void* y; } void main() { // S1, S2, and S3 should have exactly same data layout. static assert(S1.i.offsetof == S3.i.offsetof); static assert(S1.i.offsetof == S3.i.offsetof); static assert(S1.x.offsetof == S3.x.offsetof); static assert(S1.y.offsetof == S3.y.offsetof); static assert(S2.x.offsetof == S3.x.offsetof); static assert(S2.y.offsetof == S3.y.offsetof); static assert(S1.sizeof == S3.sizeof); static assert(S2.sizeof == S3.sizeof); S1 s = void; s.i = 1; assert(s.i == 1); s.x = null; assert(s.i == 1); s.y = null; assert(s.i == 1); char a, b; s.x = cast(void*)&a; assert(s.x is &a); assert(s.y is null); s.y = cast(void*)&b; assert(s.x is &a); assert(s.y is &b); }