diff --git a/src/Sema.zig b/src/Sema.zig index 338980d56f5e..10d6e4d5e609 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -28262,7 +28262,7 @@ fn elemPtrArray( block: *Block, src: LazySrcLoc, array_ptr_src: LazySrcLoc, - array_ptr: Air.Inst.Ref, + array_ptr_orig: Air.Inst.Ref, elem_index_src: LazySrcLoc, elem_index: Air.Inst.Ref, init: bool, @@ -28270,7 +28270,17 @@ fn elemPtrArray( ) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; - const array_ptr_ty = sema.typeOf(array_ptr); + const array_ptr_ty_orig = sema.typeOf(array_ptr_orig); + var array_ptr_info = array_ptr_ty_orig.ptrInfo(zcu); + + // When indexing into a C pointer of an array type, treat it as a single-item pointer to the array: ([*c][_]T)[idx] -> (*[_]T)[idx] + const array_ptr, const array_ptr_ty = if (array_ptr_info.flags.size == .c) blk: { + array_ptr_info.flags.size = .one; + const array_ptr_one_ty = try pt.ptrTypeSema(array_ptr_info); + const array_ptr_one = try block.addBitCast(array_ptr_one_ty, array_ptr_orig); + break :blk .{ array_ptr_one, array_ptr_one_ty }; + } else .{ array_ptr_orig, array_ptr_ty_orig }; + const array_ty = array_ptr_ty.childType(zcu); const array_sent = array_ty.sentinel(zcu) != null; const array_len = array_ty.arrayLen(zcu); diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index a0564fcaa055..6a8372caa298 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -786,3 +786,12 @@ test "comptime C pointer to optional pointer" { comptime assert(@TypeOf(inner_ptr) == [*c]const *u8); comptime assert(@intFromPtr(inner_ptr.*) == 0x1000); } + +test "dereference C pointer of array" { + var arr: [1]u8 = .{0}; + const arr_c_ptr = @as([*c][1]u8, &arr); + const arr_ptr = &arr; + arr_c_ptr.*[0] = 1; + try expect(arr[0] == 1); + try expect(&arr_ptr.*[0] == &arr_c_ptr.*[0]); +}