authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-04-02 06:37:41+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-04-28 19:43:58+01:00
logd038676a1f46ecab2bd095d3503ab05bcd8de58c
tree8525291c4a2fd35e61299ab2d0a19b8a110f6196
parent365ed0ed68b6f6c39b3b8f5373fbba25fe09a518

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
......@@ -28473,6 +28473,14 @@ fn elemPtrOneLayerOnly(
2847328473 try sema.checkLogicalPtrOperation(block, src, indexable_ty);
2847428474 const result_ty = try indexable_ty.elemPtrType(null, pt);
2847528475
28476 try sema.validateRuntimeElemAccess(block, elem_index_src, result_ty, indexable_ty, indexable_src);
28477 try sema.validateRuntimeValue(block, indexable_src, indexable);
28478
28479 if (!try result_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
28480 // zero-bit child type; just bitcast the pointer
28481 return block.addBitCast(result_ty, indexable);
28482 }
28483
2847628484 return block.addPtrElemPtr(indexable, elem_index, result_ty);
2847728485 },
2847828486 .one => {
......@@ -28945,6 +28953,11 @@ fn elemPtrSlice(
2894528953 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
2894628954 try sema.addSafetyCheckIndexOob(block, src, elem_index, len_inst, cmp_op);
2894728955 }
28956 if (!try slice_ty.childType(zcu).hasRuntimeBitsIgnoreComptimeSema(pt)) {
28957 // zero-bit child type; just extract the pointer and bitcast it
28958 const slice_ptr = try block.addTyOp(.slice_ptr, slice_ty.slicePtrFieldType(zcu), slice);
28959 return block.addBitCast(elem_ptr_ty, slice_ptr);
28960 }
2894828961 return block.addSliceElemPtr(slice, elem_index, elem_ptr_ty);
2894928962}
2895028963
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