diff --git a/compiler/src/dmd/templatesem.d b/compiler/src/dmd/templatesem.d index 8221c2bed6fd..161b2d1cebdc 100644 --- a/compiler/src/dmd/templatesem.d +++ b/compiler/src/dmd/templatesem.d @@ -3362,6 +3362,21 @@ bool needsCodegen(TemplateInstance ti) return true; } + // A speculative instance that contains static ctors/dtors will + // lose them if we skip codegen. Normally tinst propagates minst + // from parent to child, but tinst can be null when the instance + // was created inside StaticAssert (which clears sc.tinst). + // Walk the tempdecl parent chain as a fallback. + // https://issues.dlang.org/show_bug.cgi?id=23239 + if (!ti.minst && ti.hasStaticCtorOrDtor() && ti.tempdecl) + { + if (auto enc = ti.tempdecl.isInstantiated()) + { + if (enc.inst && enc.inst.needsCodegen()) + ti.minst = enc.inst.minst; + } + } + if (global.params.allInst) { // Do codegen if there is an instantiation from a root module, to maximize link-ability. diff --git a/compiler/test/compilable/test23239.d b/compiler/test/compilable/test23239.d new file mode 100644 index 000000000000..0e6747113015 --- /dev/null +++ b/compiler/test/compilable/test23239.d @@ -0,0 +1,21 @@ +// https://github.com/dlang/dmd/issues/23239 +// static assert instantiating a template with static this() +// should not eliminate the static this() as dead code +// when the template is also used at runtime. + +template Tmpl() +{ + int data; + template touch(T) + { + static this() { data = T.sizeof; } + enum touch = true; + } +} + +int main() +{ + static assert(Tmpl!().touch!int); // CTFE instantiation + assert(Tmpl!().data == 4); // runtime use, static this() must have run + return 0; +}