Skip to content

Fix undefined reference to internal for CTFE instance in struct .init#23188

Draft
CyberShadow wants to merge 1 commit into
dlang:stablefrom
CyberShadow:fix-20439-ctfe-internal
Draft

Fix undefined reference to internal for CTFE instance in struct .init#23188
CyberShadow wants to merge 1 commit into
dlang:stablefrom
CyberShadow:fix-20439-ctfe-internal

Conversation

@CyberShadow
Copy link
Copy Markdown
Member

A CTFE-evaluated class or struct instance baked into a struct's .init needs a local backing symbol (named "internal", STB_LOCAL) in every object module that emits the init image. That symbol was cached on the shared AST node (cre.value.origin.sym / sle.sym), so when several modules are compiled in one invocation (dmd -c a.d b.d) the symbol created for the first object module leaked into the later ones, which then emitted only an undefined reference to a local symbol they never define:

dmd -c a.d b.d
dmd a.o b.o -of=app   # undefined reference to `internal'

Fix this by tracking the literals that cache a backing symbol in the current object module and clear those caches at each object-module boundary (resetCtfeSymbolCache, called from obj_start, alongside the existing per-object resets), so every object module re-creates and emits its own self-contained local copy. This matches the array-literal path (DtBuilder.dtoff) and the separate-compilation behavior, and keeps intra-module dedup intact.

Fixes issue #20439
Fixes issue #19439

@dlang-bot
Copy link
Copy Markdown
Contributor

Thanks for your pull request, @CyberShadow!

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

⚠️⚠️⚠️ Warnings ⚠️⚠️⚠️

  • In preparation for migrating from Bugzilla to GitHub Issues, the issue reference syntax has changed. Please add the word "Bugzilla" to issue references. For example, Fix Bugzilla Issue 12345 or Fix Bugzilla 12345.(Reminder: the edit needs to be done in the Git commit message, not the GitHub pull request.)

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "stable + dmd#23188"

Comment thread compiler/test/dshell/extra-files/issue20439.d Outdated
Comment thread compiler/test/dshell/extra-files/issue20439b.d Outdated
… in struct .init with -c

A CTFE-evaluated class or struct instance baked into a struct's `.init` needs a
local backing symbol (named "internal", STB_LOCAL) in every object module that
emits the init image. That symbol was cached on the shared AST node
(`cre.value.origin.sym` / `sle.sym`), so when several modules are compiled in one
invocation (`dmd -c a.d b.d`) the symbol created for the first object module leaked
into the later ones, which then emitted only an undefined reference to a local
symbol they never define:

    dmd -c a.d b.d
    dmd a.o b.o -of=app   # undefined reference to `internal'

Track the literals that cache a backing symbol in the current object module and
clear those caches at each object-module boundary (resetCtfeSymbolCache, called
from obj_start, alongside the existing per-object resets), so every object module
re-creates and emits its own self-contained local copy. This matches the
array-literal path (DtBuilder.dtoff) and the separate-compilation behavior, and
keeps intra-module dedup intact. Also fixes the `-lib` variant (dlang#19439).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@CyberShadow CyberShadow force-pushed the fix-20439-ctfe-internal branch from a65ce99 to a4a20da Compare May 28, 2026 20:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants