test/926: pin #38b/#40 loud-stop markers + 5 more consumption-shape rows (#38 review)
Buildfail rows previously accepted ANY non-zero compiler exit — an unrelated checker error would masquerade as loud-stop coverage; now the stderr must carry the #38b/#40 marker on BOTH stages. New rows: wide_discard_stmt (generic @sretscr discard, frame canary) and four loud-stop shapes verified by probe during review — `?` consumption, `is` consumption, tagged-GLOBAL receive, struct-literal tagged field from an sret-class call (the widener #40 gate).
This commit is contained in:
@@ -356,18 +356,96 @@ static const struct row rows[] = {
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, 0, 1 },
|
||||
/* Discard statement: rides the generic @sretscr slot; the frame
|
||||
* canary pins no clobber across two discarded wide results. */
|
||||
{ "wide_discard_stmt",
|
||||
WIDE_TYPES
|
||||
"fn mk(b: []u8) (wide | oops | nomem) = {\n"
|
||||
" return wide { xs = b, ys = b, n = 1 };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let canary: i64 = 777;\n"
|
||||
" let buf: [4]u8 = [1u8, 2u8, 3u8, 4u8];\n"
|
||||
" mk(buf[0:4]);\n"
|
||||
" mk(buf[0:4]);\n"
|
||||
" if (canary != 777) { return 1; };\n"
|
||||
" return 0;\n"
|
||||
"};\n",
|
||||
0, 1, 0 },
|
||||
/* LOUD-STOP: `?` consuming an sret-class call result (cstage
|
||||
* gates at the N_LET TRYUNW/TRYPROP shape, wwstage at cgtryprop
|
||||
* — same acceptance, rule 10). */
|
||||
{ "fail_tryprop_wide",
|
||||
WIDE_TYPES
|
||||
"fn mk(b: []u8) (wide | oops | nomem) = {\n"
|
||||
" return wide { xs = b, ys = b, n = 1 };\n"
|
||||
"};\n"
|
||||
"fn go(b: []u8) (i64 | oops | nomem) = {\n"
|
||||
" let w: wide = mk(b)?;\n"
|
||||
" return w.n;\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let buf: [4]u8 = [1u8, 2u8, 3u8, 4u8];\n"
|
||||
" match (go(buf[0:4])) {\n"
|
||||
" case let v: i64 => { if (v != 1) { return 1; }; };\n"
|
||||
WIDE_MAIN_CHECK,
|
||||
0, 0, 1 },
|
||||
/* LOUD-STOP: `is` on an sret-class call result (AX = dest
|
||||
* pointer, not the tag). */
|
||||
{ "fail_typetest_wide",
|
||||
WIDE_TYPES
|
||||
"fn mk(b: []u8) (wide | oops | nomem) = {\n"
|
||||
" return wide { xs = b, ys = b, n = 1 };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let buf: [4]u8 = [1u8, 2u8, 3u8, 4u8];\n"
|
||||
" if (mk(buf[0:4]) is wide) { return 0; };\n"
|
||||
" return 1;\n"
|
||||
"};\n",
|
||||
0, 0, 1 },
|
||||
/* LOUD-STOP: sret receive into a tagged GLOBAL lvalue. */
|
||||
{ "fail_global_receive",
|
||||
WIDE_TYPES
|
||||
"let g: (wide | oops | nomem);\n"
|
||||
"fn mk(b: []u8) (wide | oops | nomem) = {\n"
|
||||
" return wide { xs = b, ys = b, n = 1 };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let buf: [4]u8 = [1u8, 2u8, 3u8, 4u8];\n"
|
||||
" g = mk(buf[0:4]);\n"
|
||||
" match (g) {\n"
|
||||
" case let w: wide => { if (w.n != 1) { return 1; }; };\n"
|
||||
WIDE_MAIN_CHECK,
|
||||
0, 0, 1 },
|
||||
/* LOUD-STOP: struct-literal FIELD of tagged type from an
|
||||
* sret-class call — the widener's cursor-spill #40 gate. */
|
||||
{ "fail_structfield_widen",
|
||||
WIDE_TYPES
|
||||
"type holder = struct { r: (wide | oops | nomem), k: i64 };\n"
|
||||
"fn mk(b: []u8) (wide | oops | nomem) = {\n"
|
||||
" return wide { xs = b, ys = b, n = 1 };\n"
|
||||
"};\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" let buf: [4]u8 = [1u8, 2u8, 3u8, 4u8];\n"
|
||||
" let h: holder = holder { r = mk(buf[0:4]), k = 5 };\n"
|
||||
" match (h.r) {\n"
|
||||
" case let w: wide => { if (w.n != 1) { return 1; }; };\n"
|
||||
WIDE_MAIN_CHECK,
|
||||
0, 0, 1 },
|
||||
};
|
||||
|
||||
static const char *g_bin;
|
||||
|
||||
/* compile one row with `tool` (w6c or w6c_ww) into outpath; returns
|
||||
* the tool's exit code. */
|
||||
/* compile one row with `tool` (w6c or w6c_ww) into outpath; stderr
|
||||
* goes to errpath so buildfail rows can pin the loud-stop marker.
|
||||
* Returns the tool's exit code. */
|
||||
static int
|
||||
compile_s(const char *tool, const char *src, const char *outpath)
|
||||
compile_s(const char *tool, const char *src, const char *outpath,
|
||||
const char *errpath)
|
||||
{
|
||||
char cmd[1024];
|
||||
snprintf(cmd, sizeof cmd, "%s/%s %s > %s 2>/dev/null",
|
||||
g_bin, tool, src, outpath);
|
||||
snprintf(cmd, sizeof cmd, "%s/%s %s > %s 2> %s",
|
||||
g_bin, tool, src, outpath, errpath);
|
||||
return runwait(cmd);
|
||||
}
|
||||
|
||||
@@ -435,20 +513,25 @@ main(void)
|
||||
for (int i = 0; i < n; i++) {
|
||||
const struct row *r = &rows[i];
|
||||
char src[128], cs_s[128], ww_s[128];
|
||||
char cs_e[128], ww_e[128];
|
||||
snprintf(src, sizeof src, "/tmp/tsret_%d_%d.ww",
|
||||
getpid(), i);
|
||||
snprintf(cs_s, sizeof cs_s, "/tmp/tsret_%d_%d_cs.s",
|
||||
getpid(), i);
|
||||
snprintf(ww_s, sizeof ww_s, "/tmp/tsret_%d_%d_ww.s",
|
||||
getpid(), i);
|
||||
snprintf(cs_e, sizeof cs_e, "/tmp/tsret_%d_%d_cs.err",
|
||||
getpid(), i);
|
||||
snprintf(ww_e, sizeof ww_e, "/tmp/tsret_%d_%d_ww.err",
|
||||
getpid(), i);
|
||||
FILE *f = fopen(src, "wb");
|
||||
if (!f) return 1;
|
||||
fputs("package main;\n\n", f);
|
||||
fputs(r->src, f);
|
||||
fclose(f);
|
||||
|
||||
int cs_rc = compile_s("w6c", src, cs_s);
|
||||
int ww_rc = compile_s("w6c_ww", src, ww_s);
|
||||
int cs_rc = compile_s("w6c", src, cs_s, cs_e);
|
||||
int ww_rc = compile_s("w6c_ww", src, ww_s, ww_e);
|
||||
if (r->buildfail) {
|
||||
total++;
|
||||
if (cs_rc == 0 || ww_rc == 0) {
|
||||
@@ -456,8 +539,18 @@ main(void)
|
||||
"expected, cstage rc=%d wwstage rc=%d\n",
|
||||
r->label, cs_rc, ww_rc);
|
||||
fail++;
|
||||
} else if (!(file_has(cs_e, "#38b") || file_has(cs_e, "#40"))
|
||||
|| !(file_has(ww_e, "#38b") || file_has(ww_e, "#40"))) {
|
||||
/* the rejection must be THE #38b/#40 loud-stop,
|
||||
* not an unrelated checker error masquerading
|
||||
* as coverage. */
|
||||
fprintf(stderr, "FAIL row[%s]: rejected but "
|
||||
"without the #38b/#40 loud-stop marker\n",
|
||||
r->label);
|
||||
fail++;
|
||||
}
|
||||
unlink(src); unlink(cs_s); unlink(ww_s);
|
||||
unlink(cs_e); unlink(ww_e);
|
||||
continue;
|
||||
}
|
||||
total++;
|
||||
@@ -466,6 +559,7 @@ main(void)
|
||||
"ww=%d\n", r->label, cs_rc, ww_rc);
|
||||
fail++;
|
||||
unlink(src); unlink(cs_s); unlink(ww_s);
|
||||
unlink(cs_e); unlink(ww_e);
|
||||
continue;
|
||||
}
|
||||
if (!file_eq(cs_s, ww_s)) {
|
||||
@@ -505,6 +599,7 @@ main(void)
|
||||
}
|
||||
}
|
||||
unlink(src); unlink(cs_s); unlink(ww_s);
|
||||
unlink(cs_e); unlink(ww_e);
|
||||
}
|
||||
if (fail) {
|
||||
fprintf(stderr, "tagged_sret_run: %d/%d rows failed\n",
|
||||
|
||||
Reference in New Issue
Block a user