Skip to content

Commit c1cc1eb

Browse files
LemonBoyandrewrk
authored andcommitted
ir: Avoid constant-folding ptr to sentinels
Constant-folding the pointers to the expected sentinel value have some big problems: it hides the real content of the array, makes the pointer to the sentinel point to a completely different memory region and treats it like a const value even when the underlying array is mutable. Fixes #4840
1 parent 8cad453 commit c1cc1eb

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

src/ir.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20880,13 +20880,8 @@ static IrInstGen *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstSrcElemP
2088020880
if (instr_is_comptime(casted_elem_index)) {
2088120881
uint64_t index = bigint_as_u64(&casted_elem_index->value->data.x_bigint);
2088220882
if (array_type->id == ZigTypeIdArray) {
20883-
uint64_t array_len = array_type->data.array.len;
20884-
if (index == array_len && array_type->data.array.sentinel != nullptr) {
20885-
ZigType *elem_type = array_type->data.array.child_type;
20886-
IrInstGen *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base.base, elem_type);
20887-
copy_const_val(ira->codegen, sentinel_elem->value, array_type->data.array.sentinel);
20888-
return ir_get_ref(ira, &elem_ptr_instruction->base.base, sentinel_elem, true, false);
20889-
}
20883+
uint64_t array_len = array_type->data.array.len +
20884+
(array_type->data.array.sentinel != nullptr);
2089020885
if (index >= array_len) {
2089120886
ir_add_error_node(ira, elem_ptr_instruction->base.base.source_node,
2089220887
buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,

test/stage1/behavior/array.zig

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,23 @@ fn getArrayLen(a: []const u32) usize {
3131
test "array with sentinels" {
3232
const S = struct {
3333
fn doTheTest(is_ct: bool) void {
34-
var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
35-
expectEqual(@as(u8, 0xde), zero_sized[0]);
36-
// Disabled at runtime because of
37-
// https://github.com/ziglang/zig/issues/4372
3834
if (is_ct) {
35+
var zero_sized: [0:0xde]u8 = [_:0xde]u8{};
36+
// Disabled at runtime because of
37+
// https://github.com/ziglang/zig/issues/4372
38+
expectEqual(@as(u8, 0xde), zero_sized[0]);
3939
var reinterpreted = @ptrCast(*[1]u8, &zero_sized);
4040
expectEqual(@as(u8, 0xde), reinterpreted[0]);
4141
}
42+
var arr: [3:0x55]u8 = undefined;
43+
// Make sure the sentinel pointer is pointing after the last element
44+
if (!is_ct) {
45+
const sentinel_ptr = @ptrToInt(&arr[3]);
46+
const last_elem_ptr = @ptrToInt(&arr[2]);
47+
expectEqual(@as(usize, 1), sentinel_ptr - last_elem_ptr);
48+
}
49+
// Make sure the sentinel is writeable
50+
arr[3] = 0x55;
4251
}
4352
};
4453

@@ -372,7 +381,7 @@ test "access the null element of a null terminated array" {
372381
const S = struct {
373382
fn doTheTest() void {
374383
var array: [4:0]u8 = .{ 'a', 'o', 'e', 'u' };
375-
comptime expect(array[4] == 0);
384+
expect(array[4] == 0);
376385
var len: usize = 4;
377386
expect(array[len] == 0);
378387
}

0 commit comments

Comments
 (0)