diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index d0bb9b4411..6a02f2912b 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -7038,7 +7038,14 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_ LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), field_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + + // The structure pointed by base_ptr may include trailing padding for + // alignment purposes and have the following LLVM type: <{ %T, [N x i8] }>. + // Add an extra bitcast as we're only interested in the %T part. + assert(handle_is_ptr(g, struct_const_val->type)); + LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, + LLVMPointerType(get_llvm_type(g, struct_const_val->type), 0)); + return LLVMConstInBoundsGEP(casted_base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) { diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index 86e9619d26..662a7383b3 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -50,6 +50,7 @@ comptime { _ = @import("behavior/bugs/4769_b.zig"); _ = @import("behavior/bugs/4769_c.zig"); _ = @import("behavior/bugs/4954.zig"); + _ = @import("behavior/bugs/5398.zig"); _ = @import("behavior/bugs/5413.zig"); _ = @import("behavior/bugs/5474.zig"); _ = @import("behavior/bugs/5487.zig"); diff --git a/test/stage1/behavior/bugs/5398.zig b/test/stage1/behavior/bugs/5398.zig new file mode 100644 index 0000000000..fdfd0b3698 --- /dev/null +++ b/test/stage1/behavior/bugs/5398.zig @@ -0,0 +1,31 @@ +const std = @import("std"); +const testing = std.testing; + +pub const Mesh = struct { + id: u32, +}; +pub const Material = struct { + transparent: bool = true, + emits_shadows: bool = true, + render_color: bool = true, +}; +pub const Renderable = struct { + material: Material, + // The compiler inserts some padding here to ensure Mesh is correctly aligned. + mesh: Mesh, +}; + +var renderable: Renderable = undefined; + +test "assignment of field with padding" { + renderable = Renderable{ + .mesh = Mesh{ .id = 0 }, + .material = Material{ + .transparent = false, + .emits_shadows = false, + }, + }; + testing.expectEqual(false, renderable.material.transparent); + testing.expectEqual(false, renderable.material.emits_shadows); + testing.expectEqual(true, renderable.material.render_color); +}