Merge pull request #7361 from ssenthilnathan3/fix/recursive-soa-sigbus

Fix: SIGBUS/segfault when compiling recursive #soa slice/dynamic array types
This commit is contained in:
Jeroen van Rijn
2026-08-17 13:16:18 +02:00
committed by GitHub
3 changed files with 67 additions and 1 deletions

View File

@@ -2617,6 +2617,22 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
return struct_type;
}
bool is_soa_struct = type->Struct.soa_kind != StructSoa_None;
LLVMTypeRef named_struct_type = nullptr;
if (is_soa_struct) {
// NOTE(bill): SOA structs are anonymous and may be recursive
// (e.g. `#soa[]T` where `T` itself contains a field of type
// `#soa[]T`). Register an opaque named struct up front so that any
// recursive field references resolve to it instead of recursing
// infinitely.
gbString soa_name = temp_canonical_string(type);
named_struct_type = LLVMGetTypeByName(m->mod, soa_name);
if (named_struct_type == nullptr) {
named_struct_type = LLVMStructCreateNamed(ctx, soa_name);
}
map_set(&m->types, type, named_struct_type);
}
lbStructFieldRemapping field_remapping = {};
slice_init(&field_remapping, permanent_allocator(), type->Struct.fields.count);
@@ -2669,7 +2685,13 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
GB_ASSERT(fields[i] != nullptr);
}
LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
LLVMTypeRef struct_type = nullptr;
if (is_soa_struct) {
struct_type = named_struct_type;
LLVMStructSetBody(struct_type, fields.data, cast(unsigned)fields.count, requires_packing);
} else {
struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, requires_packing);
}
map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping);
map_set(&m->struct_field_remapping, cast(void *)type, field_remapping);
#if 0

View File

@@ -90,6 +90,7 @@ fi
$ODIN check ../test_issue_6979.odin -no-entry-point $COMMON_CHECK
$ODIN check ../test_issue_7012.odin -no-entry-point $COMMON_CHECK
$ODIN build ../test_issue_7037.odin $COMMON -o:none
$ODIN test ../test_issue_7356.odin $COMMON
$ODIN build ../test_issue_7167.odin $COMMON
$ODIN build ../test_issue_7188.odin $COMMON

View File

@@ -0,0 +1,43 @@
// Tests issue #7356 https://github.com/odin-lang/Odin/issues/7356
// The compiler used to terminate with a SIGBUS/SIGSEGV when compiling a
// recursive `#soa` slice/dynamic array contained within its own element type.
package test_issues
import "core:testing"
Bookmark :: struct {
name: string,
children: #soa[]Bookmark,
}
DynamicBookmark :: struct {
name: string,
children: #soa[dynamic]Bookmark,
}
@(test)
test_recursive_soa_slice :: proc(t: ^testing.T) {
b: Bookmark
b.name = "root"
b.children = make(#soa[]Bookmark, 2)
defer delete(b.children)
b.children[0].name = "child0"
b.children[1].name = "child1"
testing.expect_value(t, len(b.children), 2)
testing.expect_value(t, b.children[0].name, "child0")
testing.expect_value(t, b.children[1].name, "child1")
}
@(test)
test_recursive_soa_dynamic :: proc(t: ^testing.T) {
b: DynamicBookmark
b.name = "root"
append_soa(&b.children, Bookmark{name = "child0"})
defer delete(b.children)
testing.expect_value(t, len(b.children), 1)
testing.expect_value(t, b.children[0].name, "child0")
}