www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 16471] New: [CTFE] Incorrect CTFE when assigning to union


          Issue ID: 16471
           Summary: [CTFE] Incorrect CTFE when assigning to union struct
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: major
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: jbc.engelen gmail.com

The following code asserts with DMD 2.071:
struct StructA
    this(int a)
        i = a;

    import std.typecons;
    mixin Proxy!i;

    int i;

struct TestValue
    union UnionType
        int first;
        StructA second;
        StructA third;

    UnionType value;

    this(StructA val)

    void assign(StructA val)
        value.third = val;

    void assignSecond(int val)
        value.second = StructA(val);

void main()
    enum ctObj = TestValue(StructA(1));
    // The last assigment in TestValue's construction is to value.second.
    assert(ctObj.value.second.i == 7); //
    // Note: assert(ctObj.value.third.i == 1) passes, but shouldn't.

When `enum` is changed to `auto` it all works fine.

The problem lies in a corrupt `StructLiteralExp` array of initializers
(`StructLiteralExp.elements`). In e2ir `toElemStructLit` there is a comment
"If a field has explicit initializer (*sle->elements)[i] != NULL), any other
overlapped fields won't have initializer."
This however, is not true. When assigning to union fields in `assign` and
`assignSecond`, multiple union fields will get an initializer
(`(*sle->elements)[i] != NULL`). Even without `assignSecond`, the `first` and
`second` fields will both have an initializer (this bugs LDC,
https://github.com/ldc-developers/ldc/issues/1324, where DMD's codegen
(accidentally) gets it right).

Sep 06 2016