www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 15610] New: extern(C++) multiple inheritance - calling with

https://issues.dlang.org/show_bug.cgi?id=15610

          Issue ID: 15610
           Summary: extern(C++) multiple inheritance - calling with wrong
                    'this' ptr
           Product: D
           Version: D2
          Hardware: x86_64
                OS: Windows
            Status: NEW
          Severity: blocker
          Priority: P1
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: turkeyman gmail.com

I'm seeing a case where 'this' being passed to a C++ function is wrong.
C++ multiple-inheritance calls expect that 'this' pointers are adjusted by the
offset of the base class.

Something like this:

extern(C++) class Base { ~this() {} size_t i; } // Base is 16 bytes
extern(C++) interface I { void f(); }
extern(C++) class C : Base, I
{
  final override void f();
}


C is:
{
  _vtbl,
  i,
  _I_vtbl (this+16h)
}


void code(C c)
{
  // crash:
  c.f(); passes this = 'c' to f(), but C++ expects 'c + C._I_vtbl.offsetof'
}


In this example, I have a class instance 'c', and I'm calling 'f' (introduced
by the interface), which is marked final, so D is able to perform a static call
to the C++ function with no vtable lookup.

I have managed to get this to link, and D does call the correct C++ function,
but D doesn't seem to adjust the 'this' pointer correctly for the call.

The C++ function 'f' expects that 'this' is an I pointer (not a C pointer),
which is offset by sizeof(Base) from the start of C, but D just passes 'this'
unaltered. The result is that within C::f(), the C++ code expects that 'C' is
at 'this-16h', and everything is 16 bytes out of phase leading to a prompt
crash.


TL;DR: Calling of multiple-inherited C++ interfaces requires adjustment of the
'this' pointer before making the call.

--
Jan 25 2016