Bug 13207 – Wrong code for 'extern' C/C++ function returning struct

Status
RESOLVED
Resolution
INVALID
Severity
critical
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
All
Creation time
2014-07-26T23:21:00Z
Last change time
2017-07-02T18:24:12Z
Keywords
wrong-code
Assigned to
nobody
Creator
verylonglogin.reg
See also
https://issues.dlang.org/show_bug.cgi?id=16527

Comments

Comment #0 by verylonglogin.reg — 2014-07-26T23:21:15Z
This program should run fine: D code: --- const size_t n = 8; struct S1 { long l; } // good struct S2 { byte[n] arr; } // causes errors static assert(S1.sizeof == n); static assert(S2.sizeof == n); extern(C): size_t getN() { return n; } S1 getS1() { return S1(); } // correct code S2 getS2() { return S2(); } // wrong code --- C code: --- #include<assert.h> const size_t n = 8; struct S { long long ll; }; static_assert(sizeof(S) == n, "Size mismatch."); size_t getN(); S getS1(); S getS2(); int main() { // no 'rt_init' needed. assert(getN() == n, "D struct size mismatch."); const S s1 = getS1(); const S s2 = getS2(); assert(s1.ll == 0); // ok assert(s2.ll == 0); // fails return 0; } --- Checked only on Mac OS X but this issue should also exist at least on other OS-es with System V AMD64 ABI (i.e. all except Windows). This issue makes interoperation with C/C++ stuff very difficult.
Comment #1 by verylonglogin.reg — 2014-07-26T23:23:12Z
And a C++ example where it segfaults: D code: --- const size_t n = 8; // yes, even fits in a register struct S1 { long l; } // good struct S2 { byte[n] arr; } // causes errors static assert(S1.sizeof == n); static assert(S2.sizeof == n); extern(C++) interface I { size_t getN(); S1 getS1(); S2 getS2(); } class C: I { extern(C++): size_t getN() { return n; } S1 getS1() { return S1(); } // correct code S2 getS2() { return S2(); } // wrong code } extern(C) I getI() { return new C; } --- C++ code: --- const size_t n = 8; struct S { char arr[n]; }; static_assert(sizeof(S) == n, "Size mismath."); class I { public: virtual size_t getN() = 0; virtual S getS1() = 0; virtual S getS2() = 0; }; extern "C" I *getI(); int main() { rt_init(); I *i = getI(); assert(i->getN() == n); // simple test S s1 = i->getS1(); // ok S s2 = i->getS2(); // segfaults rt_term(); return 0; } ---
Comment #2 by verylonglogin.reg — 2014-07-26T23:28:02Z
Also note there is Issue 9931, but it's marked as x86 only.
Comment #3 by dlang-bugzilla — 2017-07-02T18:24:12Z
These test cases are very badly incomplete. The C source code is incomplete, it is at least missing includes to things obviously used in the presented code, but I'm also getting numerous other errors. There are no command lines. There are no compiler versions. There is no compiler or linker output. I am closing this because this is very far from being reproducible and was filed 3 years ago. Please reopen if you can post complete, self-contained, reproducible test cases.