Bug 22318 – Calling virtual extern(C++) functions crashing or wrong

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2021-09-18T11:37:13Z
Last change time
2024-12-13T19:18:30Z
Keywords
C++
Assigned to
No Owner
Creator
Tim
Moved to GitHub: dmd#19984 →

Comments

Comment #0 by tim.dlang — 2021-09-18T11:37:13Z
While working on issue 22287 I found some other problems with extern(C++) classes with constructors. //////////////// test.d ////////////////// extern(C++): class A { this(int i); ~this(); int i; } interface I { int f() const; } class B : A, I { this(int i); override int f() const; } class D : B { this(int i) { super(i); } override int f() const { return i + 42; } } I createIFromCPP(char type, int i); B createBFromCPP(char type, int i); D createDFromCPP(int i); I createIFromD(char type, int i) { switch (type) { case 'B': return new B(i); case 'D': return new D(i); default: return null; } } B createBFromD(char type, int i) { switch (type) { case 'B': return new B(i); case 'D': return new D(i); default: return null; } } D createDFromD(int i) { return new D(i); } void runCPPTests(); extern(D) void main() { { D d = new D(100); assert(d.f() == 142); // works } { I i = createIFromCPP('D', 100); //assert(i.f() == 142); // fails, because i.f() returns 122 } { B b = createBFromCPP('D', 100); //assert(b.f() == 142); // Segmentation fault } { D d = createDFromCPP(100); //assert(d.f() == 142); // Segmentation fault } runCPPTests(); } //////////////// test.cpp //////////////// #include <assert.h> class A { public: A(int i); virtual ~A(); int i; }; class I { public: virtual int f() const = 0; }; class B : public A, public I { public: B(int i); virtual int f() const; }; class D : public B { public: D(int i); virtual int f() const; }; A::A(int i) : i(i) { } A::~A() { } B::B(int i) : A(i) { } int B::f() const { return i + 22; } I *createIFromCPP(char type, int i) { switch (type) { case 'B': return new B(i); case 'D': return new D(i); default: return 0; } } B *createBFromCPP(char type, int i) { switch (type) { case 'B': return new B(i); case 'D': return new D(i); default: return 0; } } D *createDFromCPP(int i) { D *d = new D(i); return d; } I *createIFromD(char type, int i); B *createBFromD(char type, int i); D *createDFromD(int i); void runCPPTests() { { D *d = new D(100); assert(d->f() == 142); // Segmentation fault } { I *i = createIFromD('D', 100); assert(i->f() == 142); // fails, because i.f() returns 122 } { B *b = createBFromD('D', 100); assert(b->f() == 142); // works } { D *d = createDFromD(100); assert(d->f() == 142); // works } } ////////////////////////////////////////// The issue exists under Linux and Windows. The comments describe the behaviour under Linux x86_64. Sometimes the call results in a crash. Other times it seems to call the function of a parent class. Some calls also work as expected. If the constructors are removed and A.i is set after creating the object, it works as expected.
Comment #1 by robert.schadek — 2024-12-13T19:18:30Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19984 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB