From cec9b217071ea01563f7bd924f8bf9e010ba3868 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 13 Feb 2025 21:15:27 +0100 Subject: [PATCH] Missing end padding when including a packed struct #1966. --- releasenotes.md | 1 + src/compiler/sema_decls.c | 13 +++++- test/test_suite/struct/struct_pack_error.c3t | 48 ++++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 test/test_suite/struct/struct_pack_error.c3t diff --git a/releasenotes.md b/releasenotes.md index 1a5018cfd..d6bbaaba8 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -66,6 +66,7 @@ - Fixes to ByteBuffer allocation/free. - Fix issue where compiling both for asm and object file would corrupt the obj file output. - Fix `poll` and `POLL_FOREVER`. +- Missing end padding when including a packed struct #1966. ### Stdlib changes - Added '%h' and '%H' for printing out binary data in hexadecimal using the formatter. diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 0301cfdfe..192043adc 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -486,7 +486,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl) Decl **struct_members = decl->strukt.members; unsigned member_count = vec_size(struct_members); ASSERT(member_count > 0 && "This analysis should only be called on member_count > 0"); - + bool is_naturally_aligned = !is_packed; for (unsigned i = 0; i < member_count; i++) { AGAIN:; @@ -579,6 +579,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl) // If the natural align is different from the aligned offset we have two cases: if (natural_align_offset != align_offset) { + is_naturally_aligned = false; // If the natural alignment is greater, in this case the struct is unaligned. if (member_natural_alignment > member_alignment) { @@ -604,6 +605,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl) { RETURN_SEMA_ERROR(member, "%d bytes of padding would be added to align this member which is not allowed with `@nopadding` and `@compact`.", align_offset - offset); } + member->padding = align_offset - offset; } if (!sema_check_struct_holes(context, decl, member)) return false; @@ -665,6 +667,15 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl) } decl->is_packed = is_unaligned; + // Strip padding if we are aligned. + if (!decl->is_packed && is_naturally_aligned) + { + for (unsigned i = 0; i < member_count; i++) + { + Decl *member = struct_members[i]; + member->padding = 0; + } + } decl->strukt.size = size; return true; } diff --git a/test/test_suite/struct/struct_pack_error.c3t b/test/test_suite/struct/struct_pack_error.c3t new file mode 100644 index 000000000..cb8022635 --- /dev/null +++ b/test/test_suite/struct/struct_pack_error.c3t @@ -0,0 +1,48 @@ +// #target: macos-x64 +module test; +import std; + +// issue 1966 + +struct MsgHeader @packed +{ + ulong enqueued_by_router_us; +} + +enum ClientState +{ + NOT_INITIALIZED, + WAITING_FOR_LOGIN, + READY, + WAITING_FOR_CLOSE, +} + +struct Client +{ + ClientState state; + MsgHeader header; + ushort service_id; + ElasticArray() subscribers; +} + +Client[10] clients; + +fn void main() +{ + void* a = ((void*)(&clients[0])) + Client.sizeof; + void* b = &clients[1]; +} + +/* #expect: test.ll + +%Client = type <{ i32, %MsgHeader, i16, [2 x i8], %ElasticArray }> +%MsgHeader = type { i64 } +%ElasticArray = type { i64, [1 x i64] } +define void @test.main() #0 { +entry: + %a = alloca ptr, align 8 + %b = alloca ptr, align 8 + store ptr getelementptr (i8, ptr @test.clients, i64 32), ptr %a, align 8 + store ptr getelementptr inbounds (i8, ptr @test.clients, i64 32), ptr %b, align 8 + ret void +} \ No newline at end of file