// str_field_cap_test — reading a str-typed FIELD of a struct (N_DOT value // read) must load the full 24B {ptr,len,cap} header, not just {ptr,len}, // migrated from test/wcc/933_str_field_cap_run.c (C4.6 S1+S2 case A). str is // 24B since Phase 2 (#1); pre-C4.6 the N_DOT str-field arms loaded 2 words and // dropped cap. The miscompile was cs==ww, so the 990-997 byte-id gates stayed // GREEN while the runtime was wrong — a behavioral @test is the net. // // The global row is load-bearing: in ww the global struct-field load is a // separate codegen arm with no slice sibling (cstage folds local+global in one // base_reg arm; ww splits them), so a cap-drop there would hide from the // local-field rows — hence its own @test fn. // // Each shape POISONS the source str so cap != len (a `.cap =` pseudo-field // write, no malloc / no import), then observes cap through `let s: str = // ` (a 3-word copy into the slot) and `s.cap` (an N_IDENT pseudo-field // read off the slot). spoil() interposes a CX-clobbering call between the field // store and the read so a broken 2-word read observes spoil's leftover (44), // not a stale poison the store coincidentally left behind. .len is the control. package str_field_cap_test; type rec = struct { f: str }; let g: rec; fn spoil() i32 = { let z: str = "zzzz"; z.cap = 44i32; let w: str = z; return w.cap: i32; }; @test fn s1local_field() void = { // `st.f` direct struct local field (base BP). Poison cap=8 (len=2). let p: str = "hi"; p.cap = 8i32; let st: rec; st.f = p; let junk: i32 = spoil(); let s: str = st.f; assert(s.cap: i32 == 8); assert(s.len: i32 == 2); assert(junk == 44); }; @test fn s1global_field() void = { // `g.f` direct struct global field (base CX path), the no-local-sibling // arm in ww. Poison cap=9 (len=5). let p: str = "world"; p.cap = 9i32; g.f = p; let s: str = g.f; assert(s.cap: i32 == 9); assert(s.len: i32 == 5); }; @test fn s2ptr_field() void = { // `pst.f` field via a *struct local (deref, base BX). Poison cap=7 // (len=3). let p: str = "abc"; p.cap = 7i32; let st: rec; st.f = p; let pst: *rec = &st; let s: str = pst.f; assert(s.cap: i32 == 7); assert(s.len: i32 == 3); };