From 16b741200329e7aa4fade51a786642bc5bc275a3 Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Tue, 2 Jun 2026 06:11:38 +0900 Subject: [PATCH] test/949: pin nullable (*T|void) tagged-element read byte-id (#261 deviation) --- test/wcc/949_dotbase_addr_slice_run.c | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/wcc/949_dotbase_addr_slice_run.c b/test/wcc/949_dotbase_addr_slice_run.c index 14d73eba..726f468a 100644 --- a/test/wcc/949_dotbase_addr_slice_run.c +++ b/test/wcc/949_dotbase_addr_slice_run.c @@ -657,6 +657,41 @@ static const struct row rows[] = { " case void => yield 1: i32;\n" " };\n" "};\n", 33, 1 }, + /* #261 NULLABLE-fold deviation: a (*T | void) element is the 8B + * one-word fold, NOT the 16B tag+payload slot. The fix mirrors + * cstage exactly — classify TY_TAGGED for ANY base WITHOUT excluding + * the nullable fold (slot_sz=8 degrades the copy arm to a single + * MOVQ). These rows pin that the no-exclusion path is byte-id for the + * fold too. The pointer-present / void cases prove the discriminant + * (the pointer value itself) survives materialization. The variant + * payload is read by constant (no `*p` deref) only to dodge an + * ORTHOGONAL pre-existing wwstage checker bug (asserttyped: un on a + * deref of a match-bound pointer) — distinct from #261's cgen axis. */ + { "tagged_null_ptr_rd", + "package main;\n" + "type e = struct { o: [4](*i32 | void) };\n" + "export fn main() i32 = {\n" + " let k: i32 = 7;\n" + " let x: e;\n" + " x.o[1] = &k;\n" + " let v: (*i32 | void) = x.o[1];\n" + " return match (v) {\n" + " case let p: *i32 => yield 55: i32;\n" + " case void => yield 1: i32;\n" + " };\n" + "};\n", 55, 1 }, + { "tagged_null_void_rd", + "package main;\n" + "type e = struct { o: [4](*i32 | void) };\n" + "export fn main() i32 = {\n" + " let x: e;\n" + " x.o[1] = void;\n" + " let v: (*i32 | void) = x.o[1];\n" + " return match (v) {\n" + " case let p: *i32 => yield 99: i32;\n" + " case void => yield 1: i32;\n" + " };\n" + "};\n", 1, 1 }, { NULL, NULL, 0, 0 } };