Commit f75262b79f

Andrew Kelley <andrew@ziglang.org>
2018-12-17 17:05:50
fix comptime pointer reinterpretation array index offset
closes #1835
1 parent 5a68c60
Changed files (4)
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);
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" {
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);
+}
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");