Bug 24292 – Struct with destructor wrongly returned in register

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2023-12-21T11:43:31Z
Last change time
2023-12-21T22:20:19Z
Keywords
C++, pull
Assigned to
No Owner
Creator
Tim
See also
https://issues.dlang.org/show_bug.cgi?id=20339

Comments

Comment #0 by tim.dlang — 2023-12-21T11:43:31Z
/////////////////// 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.
Comment #1 by dlang-bot — 2023-12-21T12:11:41Z
@tim-dlang updated dlang/dmd pull request #15939 "Calculate isPOD without information from semantic run" fixing this issue: - Fixes issues 20339, 24292: Calculate isPOD without information from semantic run Issue 20339: isPOD returns true if sizeof is accessed inside struct declaration Issue 24292: Struct with destructor wrongly returned in register Function StructDeclaration.isPOD can be called before the semantic run for the struct is finished. It then uses incomplete information about destructors, postblits and copy constructors. The result of isPOD is cached, so later calls will also return the wrong result. This commit changes isPOD, so it uses variables, which are already filled before the semantic run. https://github.com/dlang/dmd/pull/15939
Comment #2 by dlang-bot — 2023-12-21T22:20:19Z
dlang/dmd pull request #15939 "Fixes issues 20339, 24292: Calculate isPOD without information from semantic run" was merged into master: - 3364291b569ea832091f576d354c6e4d598315ab by Tim Schendekehl: Fixes issues 20339, 24292: Calculate isPOD without information from semantic run Issue 20339: isPOD returns true if sizeof is accessed inside struct declaration Issue 24292: Struct with destructor wrongly returned in register Function StructDeclaration.isPOD can be called before the semantic run for the struct is finished. It then uses incomplete information about destructors, postblits and copy constructors. The result of isPOD is cached, so later calls will also return the wrong result. This commit changes isPOD, so it uses variables, which are already filled before the semantic run. https://github.com/dlang/dmd/pull/15939