zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit f75262b79f0656ebfac7fb5bd2d6d8e8cce01258 (tree)
parent 5a68c600235fb7cc0e1bf6a8b314e37890e3823b
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Mon, 17 Dec 2018 11:05:50 -0500

fix comptime pointer reinterpretation array index offset

closes #1835

Diffstat:
Msrc/ir.cpp | 9++++-----
Mstd/mem.zig | 6++++++
Mtest/behavior.zig | 1+
Atest/cases/ptrcast.zig | 17+++++++++++++++++
4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/ir.cpp b/src/ir.cpp @@ -13744,20 +13744,19 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, if (array_val->data.x_array.special != ConstArraySpecialNone) zig_panic("TODO"); size_t elem_size = src_size; - src_size = elem_size * - (array_val->type->data.array.len - ptr_val->data.x_ptr.data.base_array.elem_index); + size_t elem_index = ptr_val->data.x_ptr.data.base_array.elem_index; + src_size = elem_size * (array_val->type->data.array.len - elem_index); if (dst_size > src_size) { ir_add_error_node(ira, source_node, buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes", - dst_size, buf_ptr(&array_val->type->name), ptr_val->data.x_ptr.data.base_array.elem_index, - src_size)); + dst_size, buf_ptr(&array_val->type->name), elem_index, src_size)); return ErrorSemanticAnalyzeFail; } size_t elem_count = (dst_size % elem_size == 0) ? (dst_size / elem_size) : (dst_size / elem_size + 1); Buf buf = BUF_INIT; buf_resize(&buf, elem_count * elem_size); for (size_t i = 0; i < elem_count; i += 1) { - ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[i]; + ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); } buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); diff --git a/std/mem.zig b/std/mem.zig @@ -517,6 +517,12 @@ test "comptime read/write int" { const result = std.mem.readIntBig(u16, &bytes); std.debug.assert(result == 0x3412); } + comptime { + var bytes: [2]u8 = undefined; + std.mem.writeIntBig(u16, &bytes, 0x1234); + const result = std.mem.readIntLittle(u16, &bytes); + std.debug.assert(result == 0x3412); + } } test "readIntBig and readIntLittle" { diff --git a/test/behavior.zig b/test/behavior.zig @@ -52,6 +52,7 @@ comptime { _ = @import("cases/optional.zig"); _ = @import("cases/pointers.zig"); _ = @import("cases/popcount.zig"); + _ = @import("cases/ptrcast.zig"); _ = @import("cases/pub_enum/index.zig"); _ = @import("cases/ref_var_in_if_after_if_2nd_switch_prong.zig"); _ = @import("cases/reflection.zig"); diff --git a/test/cases/ptrcast.zig b/test/cases/ptrcast.zig @@ -0,0 +1,17 @@ +const builtin = @import("builtin"); +const std = @import("std"); +const assertOrPanic = std.debug.assertOrPanic; + +test "reinterpret bytes as integer with nonzero offset" { + testReinterpretBytesAsInteger(); + comptime testReinterpretBytesAsInteger(); +} + +fn testReinterpretBytesAsInteger() void { + const bytes = "\x12\x34\x56\x78\xab"; + const expected = switch (builtin.endian) { + builtin.Endian.Little => 0xab785634, + builtin.Endian.Big => 0x345678ab, + }; + assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); +}