Commit e9bac8be6b

LemonBoy <thatlemon@gmail.com>
2020-02-25 18:35:35
ir: Fix array to slice conversion for zero-sized arrays
Closes #3848
1 parent 55ea855
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -12588,13 +12588,22 @@ static IrInstGen *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInst* sourc
 {
     Error err;
 
-    if ((err = type_resolve(ira->codegen, array_ptr->value->type->data.pointer.child_type,
-                    ResolveStatusAlignmentKnown)))
-    {
+    assert(array_ptr->value->type->id == ZigTypeIdPointer);
+
+    if ((err = type_resolve(ira->codegen, array_ptr->value->type, ResolveStatusAlignmentKnown))) {
         return ira->codegen->invalid_inst_gen;
     }
 
-    wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, array_ptr->value->type));
+    assert(array_ptr->value->type->data.pointer.child_type->id == ZigTypeIdArray);
+
+    const size_t array_len = array_ptr->value->type->data.pointer.child_type->data.array.len;
+
+    // A zero-sized array can always be casted irregardless of the destination
+    // alignment
+    if (array_len != 0) {
+        wanted_type = adjust_slice_align(ira->codegen, wanted_type,
+            get_ptr_align(ira->codegen, array_ptr->value->type));
+    }
 
     if (instr_is_comptime(array_ptr)) {
         ZigValue *array_ptr_val = ir_resolve_const(ira, array_ptr, UndefBad);
test/stage1/behavior/slice.zig
@@ -1,6 +1,7 @@
 const std = @import("std");
 const expect = std.testing.expect;
 const expectEqualSlices = std.testing.expectEqualSlices;
+const expectEqual = std.testing.expectEqual;
 const mem = std.mem;
 
 const x = @intToPtr([*]i32, 0x1000)[0..0x500];
@@ -97,3 +98,20 @@ test "obtaining a null terminated slice" {
     comptime expect(@TypeOf(ptr2) == [:0]u8);
     comptime expect(@TypeOf(ptr2[0..2]) == []u8);
 }
+
+test "empty array to slice" {
+    const S = struct {
+        fn doTheTest() void {
+            const empty: []align(16) u8 = &[_]u8{};
+            const align_1: []align(1) u8 = empty;
+            const align_4: []align(4) u8 = empty;
+            const align_16: []align(16) u8 = empty;
+            expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
+            expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
+            expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
+        }
+    };
+
+    S.doTheTest();
+    comptime S.doTheTest();
+}