wwi: derive decl-less module's .wwi package leaf from parse-stamped path (#11)

wwi_emit took the .wwi `package` leaf from the first primary decl's module tag;
a fully empty primary module body (zero decls) had none, so the leaf stayed the
literal default "main" and the importer rejected it ("package main does not
match import path <leaf>"). The module identity is only available at parse time
(curmod is overwritten by imported //ww:module sections before emit), so stamp
the primary path onto the N_FILE node (TK_MODULE and TK_MODRESET rp!=NULL sites,
only-if-empty so a bare-reset `package main` root stays "main") and, when the
decl-scan finds no leaf, fall back to that stamped path. Symmetric cstage+
selfhost; both detect scan-miss via the same found-flag so the emitted .wwi
stays byte-identical.

Regression: test/wcc/989_wwileaf_run.c, table-driven over {empty body,
comment-only, nested a.b.c} decl-less shapes, non-vacuity proven.
This commit is contained in:
2026-06-22 21:17:30 +09:00
parent a1484aef28
commit 6525e137ae
6 changed files with 352 additions and 4 deletions

View File

@@ -1442,6 +1442,13 @@ parsefile(Parser *p)
}
} else {
p->curmod = name;
/* #11: stamp the primary module identity on the
* N_FILE node so wwi_emit can derive the
* `package` leaf even when the body carries zero
* module-tagged decls. Primary identity only;
* never the imported boundary (TK_MODPATH). */
if (file->module == NULL)
file->module = name;
}
continue;
}
@@ -1478,6 +1485,13 @@ parsefile(Parser *p)
if (rp != NULL) {
p->curmod = rp;
p->resetmod = rp;
/* #11: path-carrying reset is a primary body
* identity (sep); stamp it for the wwi leaf
* fallback. A bare reset (rp==NULL) is the
* root/package-less boundary and MUST keep the
* "main" default — so do NOT stamp there. */
if (file->module == NULL)
file->module = rp;
} else {
p->curmod = NULL;
p->resetmod = NULL;