Files
ww/test/wcc/989_wwdumpgate_run.c
Hojun-Cho 2ce94a194a wwdump: -c/-r gate on parse errors
wwdump's -c/-r modes emitted output from a garbage parse silently.
Gate on the parse-error count first (the w6c main gate, main.ww:162);
wwstage-only — the C wwdump has no -c/-r modes.
2026-06-13 04:40:58 +09:00

140 lines
4.1 KiB
C

/*
* 989_wwdumpgate_run (#52, F15 c4) — wwdump_ww's `-c` and `-r` arms must gate
* on parse-stage errors instead of silently emitting on a broken AST.
*
* THE BUG (wwstage wwdump_ww only, cat-A silent wrong output under rc=0): the
* `-c` codegen arm ran checkfile+cgfile with NO parse-error gate — ps.errs
* was never read — so a parse-errored decl was silently dropped from the AST
* and the rest of the file compiled to asm with exit 0 (and `-c` IS the 994
* byte-identity probe, so the gate tool itself could ship wrong asm silently).
* The `-r` resolve report arm was likewise ungated. THE FIX: add the
* `l.errs>0 || ps.errs>0` gate after parsefile in both arms, mirroring the
* w6c compiler gate (selfhost/cmd/w6c/main.ww:162 / cmd/w6c/main.c).
*
* WWSTAGE-ONLY: the C wwdump (cstage) implements only -t/-a, not -c/-r — the
* codegen/resolve dump arms are a wwstage-wwdump_ww feature, so there is no
* cstage -c/-r twin to diff against; the gate reference is the w6c compiler.
*
* row | mode | input | result
* -------+------+---------------+----------------------------------
* bad_c | -c | parse error | rc != 0, zero asm bytes
* bad_r | -r | parse error | rc != 0
* ok_c | -c | valid file | rc == 0, asm emitted (control)
*
* bad_c / bad_r were RED pre-c4 (rc=0 with truncated asm / a resolve report).
* ok_c pins the healthy emission path unperturbed.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
static int
runwait(const char *cmd)
{
int rc = system(cmd);
if (rc == -1) return -1;
if (WIFEXITED(rc)) return WEXITSTATUS(rc);
return -1;
}
static const char *BAD =
"package main;\n\n"
"export fn main(argc: i32, argv: **u8) i32 = {\n\treturn 0;\n};\n\n"
"fn broken( {\n";
static const char *OK =
"package main;\nexport fn main() i32 = { return 0; };\n";
/* Run `<tool> <mode> <src>` capturing asm on stdout; returns rc, sets
* *asmbytes to the stdout byte count when non-NULL. */
static int
run_dump(const char *tool, const char *mode, const char *src, long *asmbytes)
{
char outp[128], cmd[1024];
snprintf(outp, sizeof outp, "/tmp/wwdg_%d_out", getpid());
snprintf(cmd, sizeof cmd, "%s %s %s > %s 2>/dev/null",
tool, mode, src, outp);
int rc = runwait(cmd);
if (asmbytes) {
FILE *f = fopen(outp, "rb");
long n = 0;
if (f) { fseek(f, 0, SEEK_END); n = ftell(f); fclose(f); }
*asmbytes = n;
}
unlink(outp);
return rc;
}
static int
write_file(const char *path, const char *body)
{
FILE *f = fopen(path, "wb");
if (!f) return -1;
fputs(body, f);
fclose(f);
return 0;
}
int
main(void)
{
const char *bin = getenv("BIN");
if (!bin) bin = "out/bin";
char absbin[1024];
if (bin[0] != '/') {
char cwd[1024];
if (getcwd(cwd, sizeof cwd) == NULL) return 1;
snprintf(absbin, sizeof absbin, "%s/%s", cwd, bin);
bin = absbin;
}
char wtool[1024];
snprintf(wtool, sizeof wtool, "%s/wwdump_ww", bin);
if (access(wtool, X_OK) != 0) {
/* wwdump_ww is the unit under test; absence is a wiring fault. */
fprintf(stderr, "wwdumpgate: missing %s\n", wtool);
return 1;
}
char badp[64], okp[64];
snprintf(badp, sizeof badp, "/tmp/wwdg_bad_%d.ww", getpid());
snprintf(okp, sizeof okp, "/tmp/wwdg_ok_%d.ww", getpid());
if (write_file(badp, BAD) || write_file(okp, OK)) return 1;
int fail = 0, total = 0;
long ab;
/* bad_c: loud, zero asm */
total++;
if (run_dump(wtool, "-c", badp, &ab) == 0 || ab != 0) {
fprintf(stderr, "wwdumpgate[bad_c]: emitted asm with rc=0 on "
"parse-errored input (#52); asm=%ld\n", ab);
fail++;
}
/* bad_r: loud */
total++;
if (run_dump(wtool, "-r", badp, NULL) == 0) {
fprintf(stderr, "wwdumpgate[bad_r]: resolve report with rc=0 on "
"parse-errored input (#52)\n");
fail++;
}
/* ok_c control: rc=0 with asm */
total++;
if (run_dump(wtool, "-c", okp, &ab) != 0 || ab <= 0) {
fprintf(stderr, "wwdumpgate[ok_c]: healthy file rejected/no asm "
"(asm=%ld)\n", ab);
fail++;
}
unlink(badp); unlink(okp);
if (fail) {
fprintf(stderr, "wwdumpgate_run: %d/%d check(s) failed\n", fail, total);
return 1;
}
printf("wwdumpgate_run: %d/%d ok\n", total, total);
return 0;
}