authorgravatar for will.lillis24@gmail.comWill Lillis <will.lillis24@gmail.com> 2024-07-25 20:52:49-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-09-01 17:31:00+03:00
log28383d4d985cd04c897f6b6a63bd2107d8e2a8e9
tree8fa7df88c64a5574bdcb0ccad579e8c578fbd336
parentcad65307b757d4dfcbae018dbdb4c2a98b87b7e3

fix(Sema): patch segfault in `finishStructInit`


2 files changed, 35 insertions(+), 4 deletions(-)

src/Sema.zig+16-4
...@@ -20345,7 +20345,12 @@ fn structInitEmpty(...@@ -20345,7 +20345,12 @@ fn structInitEmpty(
20345 defer gpa.free(field_inits);20345 defer gpa.free(field_inits);
20346 @memset(field_inits, .none);20346 @memset(field_inits, .none);
2034720347
20348 return sema.finishStructInit(block, init_src, dest_src, field_inits, struct_ty, struct_ty, false);20348 // Maps field index in the struct declaration to the field index in the initialization expression.
20349 const field_assign_idxs = try gpa.alloc(?usize, struct_ty.structFieldCount(zcu));
20350 defer gpa.free(field_assign_idxs);
20351 @memset(field_assign_idxs, null);
20352
20353 return sema.finishStructInit(block, init_src, dest_src, field_inits, field_assign_idxs, struct_ty, struct_ty, false);
20349}20354}
2035020355
20351fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {20356fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {
...@@ -20456,6 +20461,11 @@ fn zirStructInit(...@@ -20456,6 +20461,11 @@ fn zirStructInit(
20456 defer gpa.free(field_inits);20461 defer gpa.free(field_inits);
20457 @memset(field_inits, .none);20462 @memset(field_inits, .none);
2045820463
20464 // Maps field index in the struct declaration to the field index in the initialization expression.
20465 const field_assign_idxs = try gpa.alloc(?usize, resolved_ty.structFieldCount(zcu));
20466 defer gpa.free(field_assign_idxs);
20467 @memset(field_assign_idxs, null);
20468
20459 var field_i: u32 = 0;20469 var field_i: u32 = 0;
20460 var extra_index = extra.end;20470 var extra_index = extra.end;
2046120471
...@@ -20478,6 +20488,7 @@ fn zirStructInit(...@@ -20478,6 +20488,7 @@ fn zirStructInit(
20478 else20488 else
20479 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);20489 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
20480 assert(field_inits[field_index] == .none);20490 assert(field_inits[field_index] == .none);
20491 field_assign_idxs[field_index] = field_i;
20481 found_fields[field_index] = item.data.field_type;20492 found_fields[field_index] = item.data.field_type;
20482 const uncoerced_init = try sema.resolveInst(item.data.init);20493 const uncoerced_init = try sema.resolveInst(item.data.init);
20483 const field_ty = resolved_ty.fieldType(field_index, zcu);20494 const field_ty = resolved_ty.fieldType(field_index, zcu);
...@@ -20498,7 +20509,7 @@ fn zirStructInit(...@@ -20498,7 +20509,7 @@ fn zirStructInit(
20498 }20509 }
20499 }20510 }
2050020511
20501 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, result_ty, is_ref);20512 return sema.finishStructInit(block, src, src, field_inits, field_assign_idxs, resolved_ty, result_ty, is_ref);
20502 } else if (resolved_ty.zigTypeTag(zcu) == .@"union") {20513 } else if (resolved_ty.zigTypeTag(zcu) == .@"union") {
20503 if (extra.data.fields_len != 1) {20514 if (extra.data.fields_len != 1) {
20504 return sema.fail(block, src, "union initialization expects exactly one field", .{});20515 return sema.fail(block, src, "union initialization expects exactly one field", .{});
...@@ -20583,6 +20594,7 @@ fn finishStructInit(...@@ -20583,6 +20594,7 @@ fn finishStructInit(
20583 init_src: LazySrcLoc,20594 init_src: LazySrcLoc,
20584 dest_src: LazySrcLoc,20595 dest_src: LazySrcLoc,
20585 field_inits: []Air.Inst.Ref,20596 field_inits: []Air.Inst.Ref,
20597 field_assign_idxs: []?usize,
20586 struct_ty: Type,20598 struct_ty: Type,
20587 result_ty: Type,20599 result_ty: Type,
20588 is_ref: bool,20600 is_ref: bool,
...@@ -20684,9 +20696,9 @@ fn finishStructInit(...@@ -20684,9 +20696,9 @@ fn finishStructInit(
20684 }20696 }
2068520697
20686 // Find which field forces the expression to be runtime, if any.20698 // Find which field forces the expression to be runtime, if any.
20687 const opt_runtime_index = for (field_inits, 0..) |field_init, i| {20699 const opt_runtime_index = for (field_inits, field_assign_idxs) |field_init, field_assign| {
20688 if (!(try sema.isComptimeKnown(field_init))) {20700 if (!(try sema.isComptimeKnown(field_init))) {
20689 break i;20701 break field_assign;
20690 }20702 }
20691 } else null;20703 } else null;
2069220704
test/cases/compile_errors/compile_time_struct_field.zig created+19
...@@ -0,0 +1,19 @@
1const S = struct {
2 comptime_field: comptime_int = 2,
3 normal_ptr: *u32,
4};
5
6export fn a() void {
7 var value: u32 = 3;
8 const comptimeStruct = S {
9 .normal_ptr = &value,
10 };
11 _ = comptimeStruct;
12}
13
14// error
15// backend=stage2
16// target=native
17//
18// 9:6: error: unable to resolve comptime value
19// 9:6: note: initializer of comptime only struct must be comptime-known