diff --git a/bindgen-tests/tests/expectations/tests/issue-3406.rs b/bindgen-tests/tests/expectations/tests/issue-3406.rs index 258a4aea1c..f200006d88 100644 --- a/bindgen-tests/tests/expectations/tests/issue-3406.rs +++ b/bindgen-tests/tests/expectations/tests/issue-3406.rs @@ -11,6 +11,8 @@ const _: () = { ["Alignment of Inner"][::std::mem::align_of::() - 16usize]; ["Offset of field: Inner::byte"][::std::mem::offset_of!(Inner, byte) - 0usize]; }; +pub type AlignedInt = ::std::os::raw::c_int; +pub type NestedAlignedInt = AlignedInt; #[repr(C)] #[repr(align(16))] #[derive(Debug, Default, Copy, Clone)] @@ -25,3 +27,51 @@ const _: () = { ["Offset of field: Outer::before"][::std::mem::offset_of!(Outer, before) - 0usize]; ["Offset of field: Outer::inner"][::std::mem::offset_of!(Outer, inner) - 16usize]; }; +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer2 { + pub before: ::std::os::raw::c_int, + pub __bindgen_padding_0: [u8; 12usize], + pub one: AlignedInt, + pub __bindgen_padding_1: [u8; 12usize], + pub two: AlignedInt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Outer2"][::std::mem::size_of::() - 48usize]; + ["Alignment of Outer2"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Outer2::before"][::std::mem::offset_of!(Outer2, before) - 0usize]; + ["Offset of field: Outer2::one"][::std::mem::offset_of!(Outer2, one) - 16usize]; + ["Offset of field: Outer2::two"][::std::mem::offset_of!(Outer2, two) - 32usize]; +}; +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer3 { + pub before: ::std::os::raw::c_int, + pub __bindgen_padding_0: [u8; 12usize], + pub inner: AlignedInt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Outer3"][::std::mem::size_of::() - 32usize]; + ["Alignment of Outer3"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Outer3::before"][::std::mem::offset_of!(Outer3, before) - 0usize]; + ["Offset of field: Outer3::inner"][::std::mem::offset_of!(Outer3, inner) - 16usize]; +}; +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer4 { + pub before: ::std::os::raw::c_int, + pub __bindgen_padding_0: [u8; 12usize], + pub inner: NestedAlignedInt, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Outer4"][::std::mem::size_of::() - 32usize]; + ["Alignment of Outer4"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Outer4::before"][::std::mem::offset_of!(Outer4, before) - 0usize]; + ["Offset of field: Outer4::inner"][::std::mem::offset_of!(Outer4, inner) - 16usize]; +}; diff --git a/bindgen-tests/tests/headers/issue-3406.h b/bindgen-tests/tests/headers/issue-3406.h index aa3f0c1585..1b87c4bd21 100644 --- a/bindgen-tests/tests/headers/issue-3406.h +++ b/bindgen-tests/tests/headers/issue-3406.h @@ -2,7 +2,26 @@ struct __attribute__((aligned(16))) Inner { char byte; }; +typedef int AlignedInt __attribute__((aligned(16))); +typedef AlignedInt NestedAlignedInt; + struct Outer { int before; struct Inner inner; }; + +struct Outer2 { + int before; + AlignedInt one; + AlignedInt two; +}; + +struct Outer3 { + int before; + AlignedInt inner; +}; + +struct Outer4 { + int before; + NestedAlignedInt inner; +}; diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs index 805138b7a9..0519fd3d53 100644 --- a/bindgen/ir/ty.rs +++ b/bindgen/ir/ty.rs @@ -218,6 +218,15 @@ impl Type { /// What is the layout of this type? pub(crate) fn layout(&self, ctx: &BindgenContext) -> Option { + if let TypeKind::Alias(inner) | TypeKind::ResolvedTypeRef(inner) = + self.kind + { + // HACK(emilio): Rust can't represent over-aligned typedefs, so prefer the inner type's + // layout if available, to get struct layout correct at least... + if let Some(l) = ctx.resolve_type(inner).layout(ctx) { + return Some(l); + } + } self.layout.or_else(|| { match self.kind { TypeKind::Comp(ref ci) => ci.layout(ctx),