[dmd-internals] Nested Unions?

Iain Buclaw ibuclaw at ubuntu.com
Fri Oct 12 08:43:24 PDT 2012


On 12 October 2012 16:08, David Nadlinger <code at klickverbot.at> wrote:
> Earlier today, I was surprised to find out that DMD accepts the
> following program:
>
> ---
> extern(C) void printf(const char*, ...);
>
> auto create() {
>     int b = 0xdeadbeef;
>     union U {
>         int a;
>         int member() { return a; }
>         int outer() { return b; }
>     }
>     U u;
>     u.a = 0xcafebabe;
>     return u;
> }
>
> void main() {
>     auto u = create();
>     printf("%x\n", u.member());
>     printf("%x\n", u.outer());
> }
> ---
>
> It segfaults at runtime, though, when trying to load from the nested
> context pointer in U.outer(). Now, the question is: Is this really a
> bug, or just an accepts-invalid issue?
>
> I bring this up because Phobos actually contains a nested union
> (albeit without accesses to the outer scope, "U2" in the std.conv unit
> tests), which currently cause an assertion error in LDC [1].
>
> So, do we want to support nested unions just like nested structs
> (which would mean that every nested union would get a context
> pointer), or should we just disallow access of outer scopes in union
> member methods (which are quite exotic anyway).
>
> I suppose the result of applying the "turtles all the way down" rule
> differes from intuition here… C++ similarly disallows virtual
> functions in unions, probably for the same reasons, i.e. avoiding
> cases where compiler-added fields would change the union size.
>
> David
>
>
> @Andrei: Sorry for disappearing from IRC earlier, my battery went out…
>
>
> [1] The reason for the DMD runtime crash is that no nested context
> pointer is actually included in the union layout, which is caught at
> compile time in LDC due to the fact that the LLVM IR is typed.
> _______________________________________________

Not what I can see.

(gdb) p u
$1 = {a = -889275714, this = 0xcafebabe}

Which concludes that - [1] yes a context pointer is included in the
union layout, but [2] its value is never anything meaningful because
it is still a field in a union.

I'd say this is a accepts invalid bug - unions should be POD only in my opinion.


Regards
-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';


More information about the dmd-internals mailing list