test/949: slice-of-non-array-field call-arg guard rows (#257)

The #257 call-arg fix routes the N_SLICE base through the array-gated
cg_dotbase_addr/dotbaseaddr helper. Add the load-bearing deviation
guard: a slice of a []T field and of a str field passed straight as a
call arg must FALL THROUGH the gate to cgexpr (header .ptr load), not
take the field address. Both also exercise the N_DOT esz extension on
the fall-through arm (re-slice by element width). cs==ww byte-id.
This commit is contained in:
2026-06-02 04:47:56 +09:00
parent 0f2587d294
commit ca8c78e97d

View File

@@ -451,6 +451,35 @@ static const struct row rows[] = {
" a[1] = 66u8;\n"
" return rd(a[1:4]);\n"
"};\n", 66, 1 },
/* Helper-deviation guard rows (load-bearing): a slice of a NON-array
* field (`[]T` field, str field) passed as a call arg must FALL
* THROUGH the array-gated cg_dotbase_addr/dotbaseaddr to cgexpr,
* which loads the field's slice/str HEADER .ptr — NOT take the field
* ADDRESS (that would treat the header words as inline array data).
* The N_DOT esz extension also applies on the fall-through arm: the
* slice is re-sliced by the element width (esz=4 for []i32), so
* q.v[1:3][0] = backing[1]. If the gate over-fired (emitted &field),
* .ptr would point at the header itself -> wrong value / segfault. */
{ "callarg_slicefield",
"package main;\n"
"type w = struct { v: []i32 };\n"
"fn rd(s: []i32) i32 = { return s[0]; };\n"
"export fn main() i32 = {\n"
" let backing: [4]i32;\n"
" backing[1] = 88;\n"
" let q: w;\n"
" q.v = backing[0:4];\n"
" return rd(q.v[1:3]);\n"
"};\n", 88, 1 },
{ "callarg_strfield",
"package main;\n"
"type w = struct { v: str };\n"
"fn rd(s: str) i32 = { return len(s): i32; };\n"
"export fn main() i32 = {\n"
" let q: w;\n"
" q.v = \"hello\";\n"
" return rd(q.v[1:4]);\n"
"};\n", 3, 1 },
{ NULL, NULL, 0, 0 }
};