| author | |
| committer | |
| log | a859f94644cb362d84d3f9d72bc02b00a75fc32a |
| tree | e3f4d09b74fb4bca327b192d311bb5bbe950d161 |
| parent | 5ea94e7715607e986298908536cdd3d9dfdd0ce9 |
| signature |
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 #111653 files changed, 47 insertions(+), 3 deletions(-)
src/codegen/llvm.zig+4-3| ... | ... | @@ -1507,7 +1507,7 @@ pub const DeclGen = struct { |
| 1507 | 1507 | const bytes = tv.val.castTag(.bytes).?.data; |
| 1508 | 1508 | return dg.context.constString( |
| 1509 | 1509 | bytes.ptr, |
| 1510 | @intCast(c_uint, bytes.len), | |
| 1510 | @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()), | |
| 1511 | 1511 | .True, // don't null terminate. bytes has the sentinel, if any. |
| 1512 | 1512 | ); |
| 1513 | 1513 | }, |
| ... | ... | @@ -1515,10 +1515,11 @@ pub const DeclGen = struct { |
| 1515 | 1515 | const elem_vals = tv.val.castTag(.aggregate).?.data; |
| 1516 | 1516 | const elem_ty = tv.ty.elemType(); |
| 1517 | 1517 | const gpa = dg.gpa; |
| 1518 | const llvm_elems = try gpa.alloc(*const llvm.Value, elem_vals.len); | |
| 1518 | const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel()); | |
| 1519 | const llvm_elems = try gpa.alloc(*const llvm.Value, len); | |
| 1519 | 1520 | defer gpa.free(llvm_elems); |
| 1520 | 1521 | var need_unnamed = false; |
| 1521 | for (elem_vals) |elem_val, i| { | |
| 1522 | for (elem_vals[0..len]) |elem_val, i| { | |
| 1522 | 1523 | llvm_elems[i] = try dg.genTypedValue(.{ .ty = elem_ty, .val = elem_val }); |
| 1523 | 1524 | need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]); |
| 1524 | 1525 | } |
test/behavior.zig+1| ... | ... | @@ -62,6 +62,7 @@ test { |
| 62 | 62 | _ = @import("behavior/bugs/11100.zig"); |
| 63 | 63 | _ = @import("behavior/bugs/10970.zig"); |
| 64 | 64 | _ = @import("behavior/bugs/11046.zig"); |
| 65 | _ = @import("behavior/bugs/11165.zig"); | |
| 65 | 66 | _ = @import("behavior/call.zig"); |
| 66 | 67 | _ = @import("behavior/cast.zig"); |
| 67 | 68 | _ = @import("behavior/comptime_memory.zig"); |
test/behavior/bugs/11165.zig created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | test "bytes" { | |
| 4 | const S = struct { | |
| 5 | a: u32, | |
| 6 | c: [5]u8, | |
| 7 | }; | |
| 8 | ||
| 9 | const U = union { | |
| 10 | s: S, | |
| 11 | }; | |
| 12 | ||
| 13 | const s_1 = S{ | |
| 14 | .a = undefined, | |
| 15 | .c = "12345".*, // this caused problems | |
| 16 | }; | |
| 17 | _ = s_1; | |
| 18 | ||
| 19 | const u_2 = U{ .s = s_1 }; | |
| 20 | _ = u_2; | |
| 21 | } | |
| 22 | ||
| 23 | test "aggregate" { | |
| 24 | const S = struct { | |
| 25 | a: u32, | |
| 26 | c: [5]u8, | |
| 27 | }; | |
| 28 | ||
| 29 | const U = union { | |
| 30 | s: S, | |
| 31 | }; | |
| 32 | ||
| 33 | const c = [5:0]u8{ 1, 2, 3, 4, 5 }; | |
| 34 | const s_1 = S{ | |
| 35 | .a = undefined, | |
| 36 | .c = c, // this caused problems | |
| 37 | }; | |
| 38 | _ = s_1; | |
| 39 | ||
| 40 | const u_2 = U{ .s = s_1 }; | |
| 41 | _ = u_2; | |
| 42 | } |