Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion druntime/src/core/lifetime.d
Original file line number Diff line number Diff line change
Expand Up @@ -2665,8 +2665,11 @@ if (is(T == class))
enum attr = GC.convertAlignmentToBlkAttr(__traits(classInstanceAlignment, T))
/* `extern(C++)`` classes don't have a classinfo pointer in their vtable,
* so the GC can't finalize them.
* `__dtor` only exists for a user-declared destructor; `__xdtor` also
* covers destructors generated for fields that need destruction.
*/
| (__traits(hasMember, T, "__dtor") && __traits(getLinkage, T) != "C++" ? BlkAttr.FINALIZE : 0)
| ((__traits(hasMember, T, "__dtor") || __traits(hasMember, T, "__xdtor"))
&& __traits(getLinkage, T) != "C++" ? BlkAttr.FINALIZE : 0)
| (!hasIndirections!T ? BlkAttr.NO_SCAN : 0);

version(D_TypeInfo)
Expand Down Expand Up @@ -2766,6 +2769,27 @@ T* _d_newitemT(T)() @trusted
}
}

// Test that classes needing destruction are allocated as finalizable,
// including when the only destructors come from fields (no `~this()`)
@system unittest
{
import core.memory : GC;

static struct S { ~this() {} }
static class FieldDtor { S s; }
static class Dtor { ~this() {} }
static class Plain { int x; }

static bool finalizes(Object o)
{
return (GC.getAttr(cast(void*) o) & GC.BlkAttr.FINALIZE) != 0;
}

assert(finalizes(_d_newclassT!FieldDtor()));
assert(finalizes(_d_newclassT!Dtor()));
assert(!finalizes(_d_newclassT!Plain()));
}

// Test allocation
@safe unittest
{
Expand Down
5 changes: 5 additions & 0 deletions druntime/src/rt/sections_win64.d
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ extern(C) bool rt_termSharedModule(void* handle)
foreach (rng; sectionGroup._gcRanges)
GC.removeRange(rng.ptr);

// run finalizers whose code is in this module before it is unmapped
// (after module dtors, same order as rt_term and the ELF implementation)
if (auto code = findImageSection(handle, ".text"))
GC.runFinalizers(code);

finiSections(sectionGroup);
_sections.remove(i);

Expand Down
Loading