Comment #0 by andrej.mitrovich — 2014-04-22T14:37:25Z
-----
import core.sys.windows.windows;
import std.c.windows.com;
interface IFoo
{
void foo();
}
abstract class Foo : IFoo
{
void foo_impl() { }
}
class C : Foo, IUnknown
{
void foo() { }
override void foo_impl() { }
HRESULT QueryInterface(const(IID)*, void**) { return typeof(return).init; }
uint AddRef() { return typeof(return).init; }
uint Release() { return typeof(return).init; }
}
void main()
{
}
-----
Note that COM classes by default have the extern(System) calling convention, hence why the above neither implements 'foo' nor overrides 'foo_impl'. The diagnostics are:
-----
test.d(14): Error: class test.C interface function 'void foo()' is not implemented
test.d(18): Error: function test.C.foo_impl does not override any function, did you mean to override 'test.Foo.foo_impl'?
-----
The compiler should emit the calling convention of the two methods if they don't match.
Comment #1 by andrej.mitrovich — 2014-04-22T14:48:44Z
Ok so this is a bit weird, in 'InterfaceDeclaration::semantic' COM interfaces are handled like so:
if (com)
sc->linkage = LINKwindows;
else if (cpp)
sc->linkage = LINKcpp;
But in 'ClassDeclaration::semantic' the code path is different:
if (isCOMclass())
{
if (global.params.isWindows)
sc->linkage = LINKwindows;
else
/* This enables us to use COM objects under Linux and
* work with things like XPCOM
*/
sc->linkage = LINKc;
}
Is this mismatch an oversight or deliberate? It's also the reason why there are no proper diagnostics. There is a check in 'BaseClass::fillVtbl':
if (fd->linkage != ifd->linkage)
fd->error("linkage doesn't match interface function");
But the two will match in COM classes because the scope's linkage is modified, not the actual functions themselves.
So what's the best way forward?
Comment #2 by robert.schadek — 2024-12-13T18:19:54Z