// str_chained_field_cap_test — a CHAINED str-field read `o.p.f` (depth >= 2, // where p is a *struct field of o and f is a str field of *p) must load the // full 24B {ptr,len,cap} header, not just {ptr,len}, migrated from // test/wcc/934_str_chained_field_cap_run.c (C4.6 case B). str is 24B since // Phase 2 (#1); pre-caseB the chained *struct N_DOT str arm loaded 2 words (ptr // in AX, len in BX) and dropped cap. The miscompile was cs==ww, so the 990-997 // byte-id gates stayed GREEN while the runtime was wrong — behavioral @test is // the net. This is the chained sibling of str_field_cap_test (direct/single- // deref S1/S2): the lhs cgexpr leaves AX = the inner *struct pointer, then the // field is read off AX, cap from +16(AX), base (AX = ptr) read LAST. // // DISCRIMINATION: a 2-word read leaves CX untouched, so the row could // coincidentally pass if CX happened to still carry the poison cap. spoil() // interposes a CX-clobbering call between the field store and the chained read // (its own str copy leaves cap=44 in CX), so a broken read observes 44 not 8. package str_chained_field_cap_test; type inr = struct { f: str }; type otr = struct { p: *inr }; fn spoil() i32 = { let z: str = "zzzz"; z.cap = 44i32; let w: str = z; return w.cap: i32; }; @test fn caseb_chained_field() void = { // `o.p.f`: o a struct holding p: *inr, inr holding str field f. Poison // cap=8 (len=2). let p: str = "hi"; p.cap = 8i32; let ist: inr; ist.f = p; let o: otr; o.p = &ist; let junk: i32 = spoil(); let s: str = o.p.f; assert(s.cap: i32 == 8); assert(s.len: i32 == 2); assert(junk == 44); };