authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-15 22:46:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-15 22:46:39-07:00
log7c6f5d26eadb137ab3fb2be340485ebd860a85fe
tree4bdbfff4c14b9642613051d8b39e43c427ad05ea
parent0d2f4d0654af88d68fa17c813023e89c6a56c01d

Sema: populate the sentinel for comptime array inits


3 files changed, 33 insertions(+), 15 deletions(-)

src/Sema.zig+20-2
...@@ -2854,7 +2854,15 @@ fn zirValidateArrayInit(...@@ -2854,7 +2854,15 @@ fn zirValidateArrayInit(
28542854
2855 if (is_comptime or block.is_comptime) {2855 if (is_comptime or block.is_comptime) {
2856 // In this case the comptime machinery will have evaluated the store instructions2856 // In this case the comptime machinery will have evaluated the store instructions
2857 // at comptime and we have nothing to do here.2857 // at comptime so we have almost nothing to do here. However, in case of a
2858 // sentinel-terminated array, the sentinel will not have been populated by
2859 // any ZIR instructions at comptime; we need to do that here.
2860 if (array_ty.sentinel()) |sentinel_val| {
2861 const array_len_ref = try sema.addIntUnsigned(Type.usize, array_len);
2862 const sentinel_ptr = try sema.elemPtrArray(block, init_src, array_ptr, array_len_ref, init_src);
2863 const sentinel = try sema.addConstant(array_ty.childType(), sentinel_val);
2864 try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store);
2865 }
2858 return;2866 return;
2859 }2867 }
28602868
...@@ -2863,7 +2871,7 @@ fn zirValidateArrayInit(...@@ -2863,7 +2871,7 @@ fn zirValidateArrayInit(
28632871
2864 // Collect the comptime element values in case the array literal ends up2872 // Collect the comptime element values in case the array literal ends up
2865 // being comptime-known.2873 // being comptime-known.
2866 const element_vals = try sema.arena.alloc(Value, instrs.len);2874 const element_vals = try sema.arena.alloc(Value, array_ty.arrayLenIncludingSentinel());
2867 const opt_opv = try sema.typeHasOnePossibleValue(block, init_src, array_ty);2875 const opt_opv = try sema.typeHasOnePossibleValue(block, init_src, array_ty);
2868 const air_tags = sema.air_instructions.items(.tag);2876 const air_tags = sema.air_instructions.items(.tag);
2869 const air_datas = sema.air_instructions.items(.data);2877 const air_datas = sema.air_instructions.items(.data);
...@@ -2920,6 +2928,10 @@ fn zirValidateArrayInit(...@@ -2920,6 +2928,10 @@ fn zirValidateArrayInit(
2920 if (array_is_comptime) {2928 if (array_is_comptime) {
2921 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert2929 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert
2922 // instead a single `store` to the array_ptr with a comptime struct value.2930 // instead a single `store` to the array_ptr with a comptime struct value.
2931 // Also to populate the sentinel value, if any.
2932 if (array_ty.sentinel()) |sentinel_val| {
2933 element_vals[instrs.len] = sentinel_val;
2934 }
29232935
2924 block.instructions.shrinkRetainingCapacity(first_block_index);2936 block.instructions.shrinkRetainingCapacity(first_block_index);
29252937
...@@ -13436,6 +13448,12 @@ fn elemValArray(...@@ -13436,6 +13448,12 @@ fn elemValArray(
13436 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);13448 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
13437 if (maybe_index_val) |index_val| {13449 if (maybe_index_val) |index_val| {
13438 const index = @intCast(usize, index_val.toUnsignedInt());13450 const index = @intCast(usize, index_val.toUnsignedInt());
13451 const len = array_ty.arrayLenIncludingSentinel();
13452 if (index >= len) {
13453 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}", .{
13454 index, len,
13455 });
13456 }
13439 const elem_val = try array_val.elemValue(sema.arena, index);13457 const elem_val = try array_val.elemValue(sema.arena, index);
13440 return sema.addConstant(elem_ty, elem_val);13458 return sema.addConstant(elem_ty, elem_val);
13441 }13459 }
test/behavior/array_llvm.zig+13
...@@ -166,3 +166,16 @@ test "anonymous literal in array" {...@@ -166,3 +166,16 @@ test "anonymous literal in array" {
166 try S.doTheTest();166 try S.doTheTest();
167 comptime try S.doTheTest();167 comptime try S.doTheTest();
168}168}
169
170test "access the null element of a null terminated array" {
171 const S = struct {
172 fn doTheTest() !void {
173 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
174 try expect(array[4] == 0);
175 var len: usize = 4;
176 try expect(array[len] == 0);
177 }
178 };
179 try S.doTheTest();
180 comptime try S.doTheTest();
181}
test/behavior/array_stage1.zig-13
...@@ -4,19 +4,6 @@ const mem = std.mem;...@@ -4,19 +4,6 @@ const mem = std.mem;
4const expect = testing.expect;4const expect = testing.expect;
5const expectEqual = testing.expectEqual;5const expectEqual = testing.expectEqual;
66
7test "access the null element of a null terminated array" {
8 const S = struct {
9 fn doTheTest() !void {
10 var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
11 try expect(array[4] == 0);
12 var len: usize = 4;
13 try expect(array[len] == 0);
14 }
15 };
16 try S.doTheTest();
17 comptime try S.doTheTest();
18}
19
20test "type deduction for array subscript expression" {7test "type deduction for array subscript expression" {
21 const S = struct {8 const S = struct {
22 fn doTheTest() !void {9 fn doTheTest() !void {