Commit a859f94644

Mitchell Hashimoto <mitchell.hashimoto@gmail.com>
2022-03-15 00:21:11
stage2: LLVM codegen of arrays should use type length, not value length
It is possible for the value length to be longer than the type because we allow in-memory coercing of types such as `[5:0]u8` to `[5]u8`. In such a case, the value length is 6 but the type length if 5. The `.repeated` value type already got this right, so this is extending similar logic out to `.aggregate` and `.bytes`. Both scenarios are tested in behavior tests. Fixes #11165
1 parent 5ea94e7
Changed files (3)
src
codegen
test
behavior
src/codegen/llvm.zig
@@ -1507,7 +1507,7 @@ pub const DeclGen = struct {
                     const bytes = tv.val.castTag(.bytes).?.data;
                     return dg.context.constString(
                         bytes.ptr,
-                        @intCast(c_uint, bytes.len),
+                        @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()),
                         .True, // don't null terminate. bytes has the sentinel, if any.
                     );
                 },
@@ -1515,10 +1515,11 @@ pub const DeclGen = struct {
                     const elem_vals = tv.val.castTag(.aggregate).?.data;
                     const elem_ty = tv.ty.elemType();
                     const gpa = dg.gpa;
-                    const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len);
+                    const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel());
+                    const llvm_elems = try gpa.alloc(*const llvm.Value, len);
                     defer gpa.free(llvm_elems);
                     var need_unnamed = false;
-                    for (elem_vals) |elem_val, i| {
+                    for (elem_vals[0..len]) |elem_val, i| {
                         llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val });
                         need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
                     }
test/behavior/bugs/11165.zig
@@ -0,0 +1,42 @@
+const builtin = @import("builtin");
+
+test "bytes" {
+    const S = struct {
+        a: u32,
+        c: [5]u8,
+    };
+
+    const U = union {
+        s: S,
+    };
+
+    const s_1 = S{
+        .a = undefined,
+        .c = "12345".*, // this caused problems
+    };
+    _ = s_1;
+
+    const u_2 = U{ .s = s_1 };
+    _ = u_2;
+}
+
+test "aggregate" {
+    const S = struct {
+        a: u32,
+        c: [5]u8,
+    };
+
+    const U = union {
+        s: S,
+    };
+
+    const c = [5:0]u8{ 1, 2, 3, 4, 5 };
+    const s_1 = S{
+        .a = undefined,
+        .c = c, // this caused problems
+    };
+    _ = s_1;
+
+    const u_2 = U{ .s = s_1 };
+    _ = u_2;
+}
test/behavior.zig
@@ -62,6 +62,7 @@ test {
     _ = @import("behavior/bugs/11100.zig");
     _ = @import("behavior/bugs/10970.zig");
     _ = @import("behavior/bugs/11046.zig");
+    _ = @import("behavior/bugs/11165.zig");
     _ = @import("behavior/call.zig");
     _ = @import("behavior/cast.zig");
     _ = @import("behavior/comptime_memory.zig");