https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64384

--- Comment #5 from daniel.c.klauer at web dot de ---
I also think that COM is supposed to be usable from C and C++, but it seems
that here we have an exception to this rule.

Let's examine asm generated by the ms compiler for calls to GetSize(), C and
C++ versions respectively:

C++:
  ID2D1HwndRenderTarget *hwndRenderTarget;
  D2D1_SIZE_F size;
  size = hwndRenderTarget->GetSize();
Code generated by cl:
  lea   edx, DWORD PTR $T76363[ebp]                    # temp var for the
result
  push  edx                                            # hidden pointer arg
  [...push THIS arg and get function pointer from vtable into eax...]
  call  eax                     # returns pointer to temp var in eax
  mov   ecx, DWORD PTR [eax]    # reading result from temp var, 1st member
  mov   edx, DWORD PTR [eax+4]  # 2nd member of D2D1_SIZE_F
  mov   DWORD PTR _size$[ebp], ecx
  mov   DWORD PTR _size$[ebp+4], edx

C:
  ID2D1HwndRenderTarget *hwndRenderTarget;
  D2D1_SIZE_F size;
  size = hwndRenderTarget->lpVtbl->Base.GetSize(
      (ID2D1RenderTarget *)hwndRenderTarget);
Code generated by cl:
  [...push THIS arg and get function pointer into ecx...]
  call  ecx
  mov   DWORD PTR _size$[ebp], eax    # reading result from edx:eax registers
  mov   DWORD PTR _size$[ebp+4], edx

The C++ version works well; the C version crashes at the GetSize() call.
They're using incompatible aggregate return mechanisms (despite stdcall), but
since the d2d1.dll (which, I assume, implements this interface) will only use
one of the two mechanisms, the other won't work. Obviously d2d1.dll uses the
C++ version because that's what works.

Assuming this is part of MS ABI and not a bug in the MS compiler, then the
problem with gcc is that its aggregate return for C++ methods differs from MS
ABI (though it's correct for normal C-style functions).

Reply via email to