Files
ww/test/lang/alias_amp_idx_test.ww
Hojun-Cho c9c5f6406f test: migrate deref/narrow/stride family-6 to test/lang @test, retire C twins (fold-2)
Continue fold-2: migrate the pointer-deref / narrow-load / pointer-array-stride
family from bespoke build+run C twins to test/lang @test, retiring each twin in
the same commit. Runtime coverage MOVES from $(TESTS) to test-lang (T1 runs +
asserts via `ww test`) + test-lang-byteid (T2 keeps cs==ww .s byte-id); the
$(TESTS) headline drops 5. Every assert is a primitive int/bool comparison with
a width-preserving (`==`) sink so a stale high half or wrong stride FAILS; the
narrow-signed rows route through an `: i32` cast against a 64B-widened literal
to force sign-extension onto the load. Each .c row maps to one inline @test fn
(50 cases total, strict superset of the C rows):

  947_deref_narrow_run.c  -> deref_narrow_test.ww  (#116, 10 rows: *p reads pointee width not 8B MOVQ; i32/u32/u8/i8/i16/u16 + !i32-alias + enum-i8 + bool/i64 controls)
  949_ptrarr_index_run.c  -> ptrarr_index_test.ww  (#61, 23 rows: p[i]/(&p[i])/(*p)[i] stride by size(T); {1,2,4,8}B, const+var idx, param/local/cast bases, neighbor guards, nested *[2][3], *[3]str header, siphash round())
  949_dotbase_arr_run.c   -> dotbase_arr_test.ww   (#135, 3 rows: (*struct).arrayfield[i] read/write/compound addresses the field)
  944_def_amp_idx_run.c   -> def_amp_idx_test.ww   (#94, 6 rows: &D[i] over a def-array; +plain/read/2D controls)
  944_alias_amp_idx_run.c -> alias_amp_idx_test.ww (#5, 8 rows: &a[i] over an alias-typed base classifies off the chased type; local/global, narrow, fwd-ref, plain+str controls)

The two sibling .c (949_dotbase_addr_slice_run, 944_alias_def_addr_run) stay in
$(TESTS): the first is run-only byteid=0 (#254 cs!=ww rows), the second carries
a LOUD rule-7 reject row — both routed to fold-3 (task #7). Bump
LANGBYTEID_EXPECTED_MIN 38->43.
2026-06-22 13:34:28 +09:00

99 lines
3.0 KiB
Plaintext

// alias_amp_idx_test — `&a[i]` over an ALIAS-typed array base must classify
// arrayness off the CHASED type, not the syntactic tnode, migrated from
// test/wcc/944_alias_amp_idx_run.c (#5 alias arc). cgun's TK_AMP N_INDEX
// classify keyed arrayness off the syntactic tnode (N_TNAME), so `&a[i]` over an
// alias-typed base missed the N_TARRAY gate and materialized the base as MOVQ
// (element-0 VALUE) instead of LEAQ (storage address) → wild pointer, ww SEGV
// 139 on the deref (esz was already alias-correct, ONLY the base classify moved).
// cstage classifies off the chased type and is the runtime-correct reference;
// the fix re-keys both legs off tichase(base.type_) gated on TY_NAMED, so
// non-alias rows are byte-id-neutral by construction. The .s is byte-identical
// cs==ww, so these behavioral @tests are the net.
//
// All reads/writes go THROUGH THE TAKEN POINTER; values exceed 255 to break
// little-endian prefix-luck and the LAST element is checked. amp_ctrl is the
// plain-local control; amp_l1/amp_l2 are 1-/2-level alias locals; amp_order is
// the forward-ref shape (the original placed `type arr` after the use — here
// module-level resolution subsumes it); amp_narrow pins that the alias BASE was
// the only wrong half (the narrow esz was already right); amp_g1/amp_g2 are
// alias-typed globals; amp_gctrl holds the plain-global + global-str #11 legs.
//
// NOT pinned here (filed, a DIFFERENT site both stages): `&D[i]` over a
// DEF-array — covered by def_amp_idx_test (#94).
package alias_amp_idx_test;
type arr = [4]int;
type arr2 = arr;
type A = [4]u32;
let g1: arr = [1000: int, 2000: int, 3000: int, 4000: int];
let g2: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let gc: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let gs: str = "wxyz";
@test fn amp_ctrl() void = {
let a: [4]int = [1000: int, 2000: int, 3000: int, 4000: int];
let p: *int = &a[2];
assert(*p == 3000);
*p = 7777;
assert(a[2] == 7777);
let q: *int = &a[3];
assert(*q == 4000);
};
@test fn amp_l1() void = {
let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];
let p: *int = &a[3];
assert(*p == 4000);
*p = 8888;
assert(a[3] == 8888);
};
@test fn amp_l2() void = {
let a: arr2 = [1000: int, 2000: int, 3000: int, 4000: int];
let p: *int = &a[3];
assert(*p == 4000);
*p = 9999;
assert(a[3] == 9999);
};
@test fn amp_order() void = {
let a: arr = [1000: int, 2000: int, 3000: int, 4000: int];
let p: *int = &a[3];
assert(*p == 4000);
*p = 8888;
assert(a[3] == 8888);
};
@test fn amp_narrow() void = {
let a: A = [1000: u32, 2000: u32, 3000: u32, 4000: u32];
let p: *u32 = &a[3];
assert(*p == 4000);
*p = 5555;
assert(a[3] == 5555);
};
@test fn amp_g1() void = {
let p: *int = &g1[3];
assert(*p == 4000);
*p = 8888;
assert(g1[3] == 8888);
};
@test fn amp_g2() void = {
let p: *int = &g2[3];
assert(*p == 4000);
*p = 9999;
assert(g2[3] == 9999);
};
@test fn amp_gctrl() void = {
let p: *int = &gc[3];
assert(*p == 4000);
*p = 7777;
assert(gc[3] == 7777);
let q: *u8 = &gs[3];
assert(*q == 'z');
};