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).