December 21, 2023
https://issues.dlang.org/show_bug.cgi?id=24292

          Issue ID: 24292
           Summary: Struct with destructor wrongly returned in register
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: tim.dlang@t-online.de

/////////////////// test.cpp /////////////////////
template<class T>
struct List
{
    T* begin;
};

struct StructWithDestructor
{
    ~StructWithDestructor();

    int i;
};

StructWithDestructor::~StructWithDestructor()
{
}

StructWithDestructor getStructWithDestructor()
{
    StructWithDestructor r;
    r.i = 12345;
    return r;
}
//////////////////// test.d //////////////////////
extern(C++) struct List(T)
{
    // Any of the following static ifs can trigger the problem.
    static if (T.sizeof > 4) {}
    static if (__traits(isZeroInit, T)) {}
    static if (__traits(isPOD, T)) {}

    T* begin;
}

extern(C++) struct StructWithDestructor
{
    ~this();

    alias L = List!StructWithDestructor;
    int i;
}

extern(C++) StructWithDestructor getStructWithDestructor();

void main()
{
    StructWithDestructor structWithDestructor = getStructWithDestructor();
    assert(structWithDestructor.i == 12345);
}
//////////////////////////////////////////////////

The C++ function returns a struct, which is used by the D code. Currently the program crashes in getStructWithDestructor. The problem seems to be, that C++ tries to return the struct on the stack, but D expects it in a register.

This is caused by StructDeclaration.isPOD in the compiler returning true. It uses a cache, so it is only evaluated once, but calculates the wrong value on the first call, because the semantic run has not been completed for the struct at that time. A later call to isPOD could calculate the correct value, but the cache returns the wrong value. This is the same root cause as in https://issues.dlang.org/show_bug.cgi?id=20339.

It could be fixed by changing isPOD, so it does not rely on values calculated in the semantic run.

--