wcc/ww: reject duplicate top-level decls, aligned to cstage
installdecl routes all four kinds (fn/type/def/let) through installtop, which turns scopedefineinmodule's nil return into cstage's exact "duplicate <kind> <name>" reject, keyed (name,mod) so cross-package same-leaf decls coexist. Builtin redecls are dropped, not dup-errored: cstage never scopes builtins (lookup_builtin first, check.c:69), so a user redecl is dead there — wwstage mirrors via scopesamekeysym + no-source-decl test. -T synth __wwtests installs direct, mirroring check.c:3079. Closes the silent dup-fn hole (user fn run vs lib/test run built a broken test binary with no diagnostic). Per-kind reject rows + cross-package/builtin accept byte-id rows + -T collision parity row in 910/997. (#23-team, category-A addendum closed)
This commit is contained in:
@@ -265,6 +265,58 @@ linkfail(const char *bin, const char *comp)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* accept — `<comp> <fixture>` (NON-T) must exit zero. The #23 cross-package
|
||||
* legal control: distinct-mod same-leaf decls coexist, so the dup reject
|
||||
* keyed on (name, mod) must NOT fire. */
|
||||
static int
|
||||
accept(const char *bin, const char *comp, const char *fixture, const char *what)
|
||||
{
|
||||
char cmd[4096];
|
||||
snprintf(cmd, sizeof cmd, "%s/%s %s -o /dev/null 2>/dev/null",
|
||||
bin, comp, fixture);
|
||||
if (runwait(cmd) != 0) {
|
||||
fprintf(stderr, "910 FAIL: %s rejected %s (expected accept)\n",
|
||||
comp, what);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* collide_run — a @test unit defining a user `fn run` collides with
|
||||
* lib/test's bound runner once `<drv> test -c` bundles it; `<comp> -T` of
|
||||
* the combined must loud-reject the duplicate (#23). Pre-fix wwstage built
|
||||
* a binary that called the user run and silently skipped every @test. */
|
||||
static int
|
||||
collide_run(const char *bin, const char *comp, const char *drv)
|
||||
{
|
||||
int pid = getpid();
|
||||
char stem[256], comb[300], cmd[4096];
|
||||
snprintf(stem, sizeof stem, "/tmp/at910cr_%s_%d", comp, pid);
|
||||
snprintf(comb, sizeof comb, "%s.combined.ww", stem);
|
||||
snprintf(cmd, sizeof cmd,
|
||||
"%s/%s test -c -o %s test/wcc/data/attest_userrun.ww > /dev/null 2>&1",
|
||||
bin, drv, stem);
|
||||
runwait(cmd);
|
||||
if (access(comb, 0) != 0) {
|
||||
fprintf(stderr, "910 FAIL: %s build produced no %s\n", drv, comb);
|
||||
return 1;
|
||||
}
|
||||
snprintf(cmd, sizeof cmd, "%s/%s -T %s -o /dev/null 2>/dev/null",
|
||||
bin, comp, comb);
|
||||
int rc = 0;
|
||||
if (runwait(cmd) == 0) {
|
||||
fprintf(stderr, "910 FAIL: %s -T accepted user `fn run` collision "
|
||||
"(expected duplicate-fn reject)\n", comp);
|
||||
rc = 1;
|
||||
}
|
||||
unlink(comb);
|
||||
char tmp[320];
|
||||
snprintf(tmp, sizeof tmp, "%s.s", stem); unlink(tmp);
|
||||
snprintf(tmp, sizeof tmp, "%s.o", stem); unlink(tmp);
|
||||
unlink(stem);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
@@ -280,7 +332,26 @@ main(void)
|
||||
"undefined symbol in @test body") != 0) return 1;
|
||||
if (linkfail(bin, "w6c") != 0) return 1;
|
||||
|
||||
/* #23 — top-level duplicate-decl reject (one row per kind: all four
|
||||
* route through installtop, so each deserves its own pin) + legal
|
||||
* cross-package control + the builtin-redecl carve-out accept. */
|
||||
if (reject_plain(bin, "w6c", "test/wcc/data/dup_fn.ww",
|
||||
"same-module duplicate fn") != 0) return 1;
|
||||
if (reject_plain(bin, "w6c", "test/wcc/data/dup_type.ww",
|
||||
"same-module duplicate type") != 0) return 1;
|
||||
if (reject_plain(bin, "w6c", "test/wcc/data/dup_def.ww",
|
||||
"same-module duplicate def") != 0) return 1;
|
||||
if (reject_plain(bin, "w6c", "test/wcc/data/dup_let.ww",
|
||||
"same-module duplicate let") != 0) return 1;
|
||||
if (accept(bin, "w6c", "test/wcc/data/dup_xpkg_ok.ww",
|
||||
"cross-package same-name") != 0) return 1;
|
||||
if (accept(bin, "w6c", "test/wcc/data/builtin_redecl_ok.ww",
|
||||
"builtin nomem redecl (carve-out)") != 0) return 1;
|
||||
if (collide_run(bin, "w6c", "ww") != 0) return 1;
|
||||
|
||||
printf("@test -T: run ok + user-main and bad-signature rejected + "
|
||||
"non-T @test drop + checked-body + dangling-call link-fail (#6)\n");
|
||||
"non-T @test drop + checked-body + dangling-call link-fail (#6) + "
|
||||
"dup fn/type/def/let reject + xpkg + builtin-redecl accept + "
|
||||
"fn-run collision (#23)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user