Bug 15626 – extern(C++) calling crash

Status
RESOLVED
Resolution
FIXED
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2016-01-30T03:37:00Z
Last change time
2016-02-06T17:10:07Z
Keywords
C++
Assigned to
nobody
Creator
turkeyman

Attachments

IDFilenameSummaryContent-TypeSize
1581test.ziptest caseapplication/x-zip-compressed4862

Comments

Comment #0 by turkeyman — 2016-01-30T03:37:52Z
Created attachment 1581 test case D: ------------------ module lib; extern(C++) class C { } extern(C++) interface I { void f(); } extern(C++) abstract class BaseImpl(C, I) : I { C instance; } // Bonus points: this is extern(C) because the C++ mangler doesn't work on this type. extern(C) void test(BaseImpl!(C, I) impl) { impl.f(); } C++: ------------------ #include <stdio.h> class C { }; class I { virtual void f() = 0; }; template <typename C, typename I> class BaseImpl : public I { C *pInstance = (C*)(size_t)0xBAADF00D; }; class Impl : public BaseImpl<C, I> { void f() override final { printf("!!"); } }; extern "C" { extern void test(BaseImpl<C, I> *pImpl); } void main() { Impl *i = new Impl; test(i); }
Comment #1 by bugzilla — 2016-01-30T07:54:53Z
Thanks, Manu. The first thing I notice is main() is in C++. This will not work because it will bypass the D runtime initialization. That isn't what this bug is about, though. I'll see what I can do with this.
Comment #2 by bugzilla — 2016-01-30T08:15:06Z
Stripping away the unnecessary template and complex names: ---------- D ----------------- extern(C++) { class C { } interface I { void f(); } abstract class Base : I { int instance; } void test(Base b) { b.f(); } void mainx(); } int main() { mainx(); return 0; } ------------- C++ ------------ #include <stdio.h> class C { }; class I { virtual void f() = 0; }; class Base : public I { public: int pInstance; Base() { pInstance = 0xBAADF00D; } }; class Derived : public Base { public: void f() { printf("!!"); } }; void test(Base *b); void mainx() { Derived *d = new Derived; test(d); }
Comment #3 by bugzilla — 2016-02-01T04:09:52Z
As a workaround, if you create a base class for 'Base' that contains a virtual function, in both the D and C++ code, it will work.
Comment #4 by bugzilla — 2016-02-05T10:52:21Z
https://github.com/D-Programming-Language/dmd/pull/5403 There's no easy way to hack this in. The trouble is you have a C++ base class with no virtual functions, so it has no vtbl[]. I.e. is it not a class at all, it is a struct. This is not supported. The way to fix the code is to replace interface I with abstract class I, move the fields from C into I, and ditch class C entirely.
Comment #5 by github-bugzilla — 2016-02-06T17:10:06Z
Commits pushed to master at https://github.com/D-Programming-Language/dmd https://github.com/D-Programming-Language/dmd/commit/6d01b29c86aab514cf40d6657bad866c9f7fb4e8 fix Issue 15626 - extern(C++) calling crash https://github.com/D-Programming-Language/dmd/commit/bbbba7b358a2824bab8421b0455b613d2b899f40 Merge pull request #5403 from WalterBright/fix15626 fix Issue 15626 - extern(C++) calling crash