diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 3a3b4ac196..ce2c7aea22 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -765,6 +765,7 @@ pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClang pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl; pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl; pub extern fn ZigClangFieldDecl_getCanonicalDecl(field_decl: ?*const struct_ZigClangFieldDecl) ?*const struct_ZigClangFieldDecl; +pub extern fn ZigClangFieldDecl_getAlignedAttribute(field_decl: ?*const struct_ZigClangFieldDecl, *const ZigClangASTContext) c_uint; pub extern fn ZigClangEnumDecl_getCanonicalDecl(self: ?*const struct_ZigClangEnumDecl) ?*const struct_ZigClangTagDecl; pub extern fn ZigClangTypedefNameDecl_getCanonicalDecl(self: ?*const struct_ZigClangTypedefNameDecl) ?*const struct_ZigClangTypedefNameDecl; pub extern fn ZigClangFunctionDecl_getCanonicalDecl(self: ?*const struct_ZigClangFunctionDecl) ?*const struct_ZigClangFunctionDecl; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 8af98a3bf0..f14ebe3306 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -632,7 +632,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { const align_expr = blk: { const alignment = ZigClangVarDecl_getAlignedAttribute(var_decl, rp.c.clang_context); if (alignment != 0) { - _ = try appendToken(rp.c, .Keyword_linksection, "align"); + _ = try appendToken(rp.c, .Keyword_align, "align"); _ = try appendToken(rp.c, .LParen, "("); // Clang reports the alignment in bits const expr = try transCreateNodeInt(rp.c, alignment / 8); @@ -827,6 +827,20 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* else => |e| return e, }; + const align_expr = blk: { + const alignment = ZigClangFieldDecl_getAlignedAttribute(field_decl, rp.c.clang_context); + if (alignment != 0) { + _ = try appendToken(rp.c, .Keyword_align, "align"); + _ = try appendToken(rp.c, .LParen, "("); + // Clang reports the alignment in bits + const expr = try transCreateNodeInt(rp.c, alignment / 8); + _ = try appendToken(rp.c, .RParen, ")"); + + break :blk expr; + } + break :blk null; + }; + const field_node = try c.a().create(ast.Node.ContainerField); field_node.* = .{ .doc_comments = null, @@ -834,7 +848,7 @@ fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?* .name_token = field_name, .type_expr = field_type, .value_expr = null, - .align_expr = null, + .align_expr = align_expr, }; if (is_anon) { @@ -4607,7 +4621,7 @@ fn finishTransFnProto( if (fn_decl) |decl| { const alignment = ZigClangFunctionDecl_getAlignedAttribute(decl, rp.c.clang_context); if (alignment != 0) { - _ = try appendToken(rp.c, .Keyword_linksection, "align"); + _ = try appendToken(rp.c, .Keyword_align, "align"); _ = try appendToken(rp.c, .LParen, "("); // Clang reports the alignment in bits const expr = try transCreateNodeInt(rp.c, alignment / 8); diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index c5ea182e87..ca93634aab 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -1615,6 +1615,16 @@ unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, return 0; } +unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx) { + auto casted_self = reinterpret_cast(self); + auto casted_ctx = const_cast(reinterpret_cast(ctx)); + if (const clang::AlignedAttr *AA = casted_self->getAttr()) { + return AA->getAlignment(*casted_ctx); + } + // Zero means no explicit alignment factor was specified + return 0; +} + unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx) { auto casted_self = reinterpret_cast(self); auto casted_ctx = const_cast(reinterpret_cast(ctx)); diff --git a/src/zig_clang.h b/src/zig_clang.h index 579812a84a..af4b04c776 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -865,6 +865,7 @@ ZIG_EXTERN_C const struct ZigClangVarDecl *ZigClangVarDecl_getCanonicalDecl(cons ZIG_EXTERN_C const char* ZigClangVarDecl_getSectionAttribute(const struct ZigClangVarDecl *self, size_t *len); ZIG_EXTERN_C unsigned ZigClangVarDecl_getAlignedAttribute(const struct ZigClangVarDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C unsigned ZigClangFunctionDecl_getAlignedAttribute(const struct ZigClangFunctionDecl *self, const ZigClangASTContext* ctx); +ZIG_EXTERN_C unsigned ZigClangFieldDecl_getAlignedAttribute(const struct ZigClangFieldDecl *self, const ZigClangASTContext* ctx); ZIG_EXTERN_C struct ZigClangQualType ZigClangParmVarDecl_getOriginalType(const struct ZigClangParmVarDecl *self); diff --git a/test/translate_c.zig b/test/translate_c.zig index 471e1eca51..e21c3c49ae 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,6 +3,16 @@ const std = @import("std"); const CrossTarget = std.zig.CrossTarget; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("struct with aligned fields", + \\struct foo { + \\ __attribute__((aligned(1))) short bar; + \\}; + , &[_][]const u8{ + \\pub const struct_foo = extern struct { + \\ bar: c_short align(1), + \\}; + }); + cases.add("structs with VLAs are rejected", \\struct foo { int x; int y[]; }; \\struct bar { int x; int y[0]; };