From f82d41bc9a60f12ff4905b40dafd67d775432083 Mon Sep 17 00:00:00 2001 From: Gustavo Konrad Date: Sat, 28 Feb 2026 12:33:57 -0300 Subject: [PATCH] fix #6344: field-first index writes on #soa[dynamic]T and #soa[]T --- src/llvm_backend_expr.cpp | 6 ++- tests/issues/run.sh | 2 + tests/issues/test_issue_6344.odin | 72 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/issues/test_issue_6344.odin diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 81d7a4e36..35464af21 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4654,6 +4654,8 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } } lbValue val = lb_emit_ptr_offset(p, field, index); + // make sure it's ^T and not [^]T + val.type = alloc_type_multi_pointer_to_pointer(val.type); return lb_addr(val); } @@ -5795,8 +5797,8 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { if (sub_sel.index.count > 0) { item = lb_emit_deep_field_gep(p, item, sub_sel); } - // make sure it's ^T and not [^]T - item.type = alloc_type_multi_pointer_to_pointer(item.type); + // make sure it's ^T and not [^]T + item.type = alloc_type_multi_pointer_to_pointer(item.type); return lb_addr(item); } else if (addr.kind == lbAddr_Swizzle) { diff --git a/tests/issues/run.sh b/tests/issues/run.sh index 73d0d9587..a5323dc45 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -36,6 +36,8 @@ $ODIN test ../test_issue_5699.odin $COMMON $ODIN test ../test_issue_6068.odin $COMMON $ODIN test ../test_issue_6101.odin $COMMON $ODIN test ../test_issue_6165.odin $COMMON +$ODIN test ../test_issue_6344.odin $COMMON +$ODIN test ../test_issue_6344.odin $COMMON -o:speed set +x popd diff --git a/tests/issues/test_issue_6344.odin b/tests/issues/test_issue_6344.odin new file mode 100644 index 000000000..834ca25db --- /dev/null +++ b/tests/issues/test_issue_6344.odin @@ -0,0 +1,72 @@ +// Tests issue #6344 https://github.com/odin-lang/Odin/issues/6344 +package test_issues + +import "core:testing" + +@(test) +test_soa_dynamic_field_write :: proc(t: ^testing.T) { + V :: struct { + x: f32, + y: f32, + } + + array := make(#soa[dynamic]V, 4, 8) + defer delete(array) + + for i in 0 ..< 4 { + array[i] = V{f32(i), f32(i) * 2} + } + + // Simple write through field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + array.x[i] = f32(i) * 10 + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 10) + testing.expect_value(t, array[2].x, 20) + testing.expect_value(t, array[3].x, 30) + + // Compound write through field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + array.x[i] += array.y[i] + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 12) + testing.expect_value(t, array[2].x, 24) + testing.expect_value(t, array[3].x, 36) +} + +@(test) +test_soa_slice_field_write :: proc(t: ^testing.T) { + V :: struct { + x: f32, + y: f32, + } + + array := make(#soa[dynamic]V, 4, 8) + defer delete(array) + + for i in 0 ..< 4 { + array[i] = V{f32(i), f32(i) * 2} + } + + slice := array[:] + + // Write through slice field-first indexing (was: compiler panic) + for i in 0 ..< 4 { + slice.x[i] = f32(i) * 10 + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 10) + testing.expect_value(t, array[2].x, 20) + testing.expect_value(t, array[3].x, 30) + + // Compound write through slice field-first indexing + for i in 0 ..< 4 { + slice.x[i] += slice.y[i] + } + testing.expect_value(t, array[0].x, 0) + testing.expect_value(t, array[1].x, 12) + testing.expect_value(t, array[2].x, 24) + testing.expect_value(t, array[3].x, 36) +}