Issue 15205 - Incorrect struct init via union array
Summary: Incorrect struct init via union array
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P3 normal
Assignee: No Owner
URL:
Keywords: wrong-code
: 18313 (view as issue list)
Depends on:
Blocks:
 
Reported: 2015-10-15 15:28 UTC by d bug report
Modified: 2024-11-05 17:33 UTC (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description d bug report 2015-10-15 15:28:41 UTC
Tested with: D2.068.1 and D2.069.b

struct Foo
{
    this( float x_, float y_ )
    {
        // option A
        //x = x_;
        //y = y_;

        // option B
        v[0] = x_;
        v[1] = y_;
    }

    union
    {
        struct
        {
            float x = 0;
            float y = 0;
        }
        float[2] v;
    }
}

struct Bar
{
    Foo foo = Foo( 1, 2 );
}

Bar bar;
Bar baz = bar.init;

printf( "bar: %f, %f\n", bar.foo.x, bar.foo.y );
printf( "baz: %f, %f\n", baz.foo.x, baz.foo.y );
-------------------------------------------------
prints (with option B):
bar: 0.000000, 0.000000   // BUG??
baz: 1.000000, 2.000000

prints (with option A):
bar: 1.000000, 2.000000
baz: 1.000000, 2.000000
Comment 1 Vladimir Panteleev 2015-10-27 08:50:02 UTC
Note: before https://github.com/D-Programming-Language/dmd/pull/2681 this caused a compile-time error:

test.d(29): Error: duplicate union initialization for v

Perhaps this should still result in an error due to incomplete implementation of unions in CTFE.
Comment 2 skocznymr 2019-07-21 19:43:43 UTC
Encountered what seems to be the same issue. Reproduces on DMD 2.084.0 and LDC 1.13.0

import std.stdio;

struct Foo
{
    static Foo initializedFoo()
    {
        Foo x;
        x.a_array[0] = 1;
        return x;
    }

    union
    {
        float a;
        float[1] a_array;
    }
}

Foo bar = Foo.initializedFoo();

void main()
{
    writeln(bar.a);
    writeln(bar.a_array);
}

returns nan [nan] instead of 1 [1]
Comment 3 skocznymr 2019-11-24 12:00:12 UTC
*** Issue 18313 has been marked as a duplicate of this issue. ***
Comment 4 Steven Schveighoffer 2024-11-05 17:33:44 UTC
Just helping out someone in discord, and ran into what looks like the same issue.

What seems to happen is if the non-first union member is a static array, and that array is set via indexing items, then it does not set the internal tag for the union during CTFE, so it doesn't think the second member is set, and instead writes out the first member.

Change option B to:

```d
v = v.init;
v[0] = x_;
v[1] = y_;
``` 

and it works. What I think happens is the assignment to v sets the union tag.

If you set v all at once, it also works:

```d
v = [x_, y_];
```

I think the compiler should detect the initialization via the indexed usage and set the tag properly.