Skip to content

Commit

Permalink
Fix bugzilla issue 24882 - COM class is allocated using GC not malloc
Browse files Browse the repository at this point in the history
  • Loading branch information
rikkimax committed Nov 26, 2024
1 parent 4c645bb commit eb3b215
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 1 deletion.
5 changes: 5 additions & 0 deletions changelog/dmd.isCOMClass.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
New trait isCOMClass to detect if a type is a COM class

A COM class inherits from a possibly user defined interface called ``IUnknown``.
To detect this during compilation use the trait ``__traits(isCOMClass, Type)``.
Or using the ``TypeInfo_Class`` flag.
1 change: 1 addition & 0 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -8692,6 +8692,7 @@ struct Id final
static Identifier* isRef;
static Identifier* isOut;
static Identifier* isLazy;
static Identifier* isCOMClass;
static Identifier* hasMember;
static Identifier* identifier;
static Identifier* fullyQualifiedName;
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/id.d
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ immutable Msgtable[] msgtable =
{ "isRef" },
{ "isOut" },
{ "isLazy" },
{ "isCOMClass" },
{ "hasMember" },
{ "identifier" },
{ "fullyQualifiedName" },
Expand Down
20 changes: 20 additions & 0 deletions compiler/src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,26 @@ Expression semanticTraits(TraitsExp e, Scope* sc)

return isDeclX(d => (d.storage_class & STC.lazy_) != 0);
}
if (e.ident == Id.isCOMClass)
{
if (dim != 1)
return dimError(1);

Check warning on line 699 in compiler/src/dmd/traits.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/traits.d#L699

Added line #L699 was not covered by tests

auto o = (*e.args)[0];
auto s = getDsymbol(o);
AggregateDeclaration agg;

if (!s || ((agg = s.isAggregateDeclaration()) is null))
{
error(e.loc, "argument to `__traits(isCOMClass, %s)` is not a declaration", o.toChars());
return ErrorExp.get();

Check warning on line 708 in compiler/src/dmd/traits.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/traits.d#L707-L708

Added lines #L707 - L708 were not covered by tests
}

if (ClassDeclaration cd = agg.isClassDeclaration())
return cd.com ? True() : False();
else
return False();

Check warning on line 714 in compiler/src/dmd/traits.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/traits.d#L714

Added line #L714 was not covered by tests
}
if (e.ident == Id.identifier)
{
// Get identifier for symbol as a string literal
Expand Down
4 changes: 4 additions & 0 deletions compiler/test/runnable/test36.d
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ extern (Windows):
{printf(`comobject\n`);
}
}

// https://issues.dlang.org/show_bug.cgi?id=24882
static assert(__traits(isCOMClass, ComObject));

interface IDataObject: IUnknown
{
extern(Windows):
Expand Down
5 changes: 4 additions & 1 deletion druntime/src/core/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -2739,8 +2739,11 @@ if (is(T == class))
auto init = __traits(initSymbol, T);
void* p;

static if (__traits(getLinkage, T) == "Windows")
static if (__traits(isCOMClass, T))
{
// If this is a COM class we allocate it using malloc.
// This allows the reference counting to outlive the reference known about by the GC.

p = pureMalloc(init.length);
if (!p)
onOutOfMemoryError();
Expand Down

0 comments on commit eb3b215

Please sign in to comment.