authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-23 16:46:50-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-23 16:46:50-04:00
loga2b0b0015d8a0c7aff451ae723ed2f30360ca33f
tree8af430e781e1913c13dbdf5a158e457a03dd965d
parentb872539a13ac46abe57a59bafdf5392812468482
parent41e300adf17bc4056c574b32de4e07f129f2bd24
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11273 from topolarity/bugfix-11272

stage2: Properly "flatten" elem_ptrs before deref

2 files changed, 31 insertions(+), 25 deletions(-)

src/Sema.zig+10-25
......@@ -17045,17 +17045,9 @@ fn elemVal(
1704517045 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
1704617046 const index_val = maybe_index_val orelse break :rs elem_index_src;
1704717047 const index = @intCast(usize, index_val.toUnsignedInt(target));
17048 const elem_ty = indexable_ty.elemType2();
17049
17050 var payload: Value.Payload.ElemPtr = .{ .data = .{
17051 .array_ptr = indexable_val,
17052 .elem_ty = elem_ty,
17053 .index = index,
17054 } };
17055 const elem_ptr_val = Value.initPayload(&payload.base);
17056
17048 const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, target);
1705717049 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {
17058 return sema.addConstant(elem_ty, elem_val);
17050 return sema.addConstant(indexable_ty.elemType2(), elem_val);
1705917051 }
1706017052 break :rs indexable_src;
1706117053 };
......@@ -17310,12 +17302,7 @@ fn elemValSlice(
1731017302 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
1731117303 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
1731217304 }
17313 var elem_ptr_pl: Value.Payload.ElemPtr = .{ .data = .{
17314 .array_ptr = slice_val.slicePtr(),
17315 .elem_ty = elem_ty,
17316 .index = index,
17317 } };
17318 const elem_ptr_val = Value.initPayload(&elem_ptr_pl.base);
17305 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, target);
1731917306 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {
1732017307 return sema.addConstant(elem_ty, elem_val);
1732117308 }
......@@ -18765,6 +18752,11 @@ fn beginComptimePtrLoad(
1876518752 const elem_ty = elem_ptr.elem_ty;
1876618753 var deref = try beginComptimePtrLoad(sema, block, src, elem_ptr.array_ptr, null);
1876718754
18755 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
18756 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
18757 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
18758 if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, target)));
18759
1876818760 if (elem_ptr.index != 0) {
1876918761 if (elem_ty.hasWellDefinedLayout()) {
1877018762 if (deref.parent) |*parent| {
......@@ -18793,13 +18785,6 @@ fn beginComptimePtrLoad(
1879318785
1879418786 var array_tv = deref.pointee.?;
1879518787 const check_len = array_tv.ty.arrayLenIncludingSentinel();
18796 if (elem_ptr.index >= check_len) {
18797 // TODO have the deref include the decl so we can say "declared here"
18798 return sema.fail(block, src, "comptime load of index {d} out of bounds of array length {d}", .{
18799 elem_ptr.index, check_len,
18800 });
18801 }
18802
1880318788 if (maybe_array_ty) |load_ty| {
1880418789 // It's possible that we're loading a [N]T, in which case we'd like to slice
1880518790 // the pointee array directly from our parent array.
......@@ -18813,10 +18798,10 @@ fn beginComptimePtrLoad(
1881318798 }
1881418799 }
1881518800
18816 deref.pointee = .{
18801 deref.pointee = if (elem_ptr.index < check_len) TypedValue{
1881718802 .ty = elem_ty,
1881818803 .val = try array_tv.val.elemValue(sema.arena, elem_ptr.index),
18819 };
18804 } else null;
1882018805 break :blk deref;
1882118806 },
1882218807
test/behavior/eval.zig+21
......@@ -1,5 +1,6 @@
11const builtin = @import("builtin");
22const std = @import("std");
3const assert = std.debug.assert;
34const expect = std.testing.expect;
45const expectEqual = std.testing.expectEqual;
56
......@@ -830,3 +831,23 @@ test "const type-annotated local initialized with function call has correct type
830831 try expect(@TypeOf(x) == u64);
831832 try expect(x == 1234);
832833}
834
835test "comptime pointer load through elem_ptr" {
836 const S = struct {
837 x: usize,
838 };
839
840 comptime {
841 var array: [10]S = undefined;
842 for (array) |*elem, i| {
843 elem.* = .{
844 .x = i,
845 };
846 }
847 var ptr = @ptrCast([*]S, &array);
848 var x = ptr[0].x;
849 assert(x == 0);
850 ptr += 1;
851 assert(ptr[1].x == 2);
852 }
853}