authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-04-02 06:37:41+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-04-28 20:48:24+02:00
logbee19572c83c77995ca9a1206a6b08606f65eaa7
treed5f98142584f04be404c35a338008d0f0528f8dc
parentb5c22777f839f926ff3e272c9285d4d3e6402c0d
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

Sema: fix a few indexing bugs

* Indexing zero-bit types should not produce AIR indexing instructions * Getting a runtime-known element pointer from a many-pointer should check that the many-pointer is not comptime-only Resolves: #23405

3 files changed, 47 insertions(+), 0 deletions(-)

src/Sema.zig+13
......@@ -29037,6 +29037,14 @@ fn elemPtrOneLayerOnly(
2903729037 }
2903829038 const result_ty = try indexable_ty.elemPtrType(null, pt);
2903929039
29040 try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src);
29041 try sema.validateRuntimeValue(block, indexable_src, indexable);
29042
29043 if (!try result_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
29044 // zero-bit child type; just bitcast the pointer
29045 return block.addBitCast(result_ty, indexable);
29046 }
29047
2904029048 return block.addPtrElemPtr(indexable, elem_index, result_ty);
2904129049 },
2904229050 .one => {
......@@ -29497,6 +29505,11 @@ fn elemPtrSlice(
2949729505 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
2949829506 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
2949929507 }
29508 if (!try slice_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
29509 // zero-bit child type; just extract the pointer and bitcast it
29510 const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice);
29511 return block.addBitCast(elem_ptr_ty, slice_ptr);
29512 }
2950029513 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
2950129514}
2950229515
test/behavior/pointers.zig+24
......@@ -760,3 +760,27 @@ test "comptime pointer equality through distinct elements with well-defined layo
760760 comptime assert(buf[1] == 456);
761761 comptime assert(second_elem.* == 456);
762762}
763
764test "pointers to elements of slice of zero-bit type" {
765 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
766
767 var slice: []const u0 = undefined;
768 slice = &.{ 0, 0 };
769
770 const a = &slice[0];
771 const b = &slice[1];
772
773 try expect(a == b);
774}
775
776test "pointers to elements of many-ptr to zero-bit type" {
777 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
778
779 var many_ptr: [*]const u0 = undefined;
780 many_ptr = &.{ 0, 0 };
781
782 const a = &many_ptr[0];
783 const b = &many_ptr[1];
784
785 try expect(a == b);
786}
test/cases/compile_errors/runtime_index_into_comptime_only_many_ptr.zig created+10
......@@ -0,0 +1,10 @@
1var rt: usize = 0;
2export fn foo() void {
3 const x: [*]const type = &.{ u8, u16 };
4 _ = &x[rt];
5}
6
7// error
8//
9// :4:12: error: values of type '[*]const type' must be comptime-known, but index value is runtime-known
10// :4:11: note: types are not available at runtime