diff --git a/bindgen-tests/tests/expectations/tests/issue-3406.rs b/bindgen-tests/tests/expectations/tests/issue-3406.rs new file mode 100644 index 0000000000..258a4aea1c --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-3406.rs @@ -0,0 +1,27 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Inner { + pub byte: ::std::os::raw::c_char, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Inner"][::std::mem::size_of::() - 16usize]; + ["Alignment of Inner"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Inner::byte"][::std::mem::offset_of!(Inner, byte) - 0usize]; +}; +#[repr(C)] +#[repr(align(16))] +#[derive(Debug, Default, Copy, Clone)] +pub struct Outer { + pub before: ::std::os::raw::c_int, + pub inner: Inner, +} +#[allow(clippy::unnecessary_operation, clippy::identity_op)] +const _: () = { + ["Size of Outer"][::std::mem::size_of::() - 32usize]; + ["Alignment of Outer"][::std::mem::align_of::() - 16usize]; + ["Offset of field: Outer::before"][::std::mem::offset_of!(Outer, before) - 0usize]; + ["Offset of field: Outer::inner"][::std::mem::offset_of!(Outer, inner) - 16usize]; +}; diff --git a/bindgen-tests/tests/expectations/tests/layout_array.rs b/bindgen-tests/tests/expectations/tests/layout_array.rs index dd34681a5d..9a197b0232 100644 --- a/bindgen-tests/tests/expectations/tests/layout_array.rs +++ b/bindgen-tests/tests/expectations/tests/layout_array.rs @@ -1,12 +1,4 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] -#[repr(C, align(8))] -pub struct __BindgenOpaqueArray8(pub T); -impl Default for __BindgenOpaqueArray8<[T; N]> { - fn default() -> Self { - Self([::default(); N]) - } -} pub const RTE_CACHE_LINE_SIZE: u32 = 64; pub const RTE_MEMPOOL_OPS_NAMESIZE: u32 = 32; pub const RTE_MEMPOOL_MAX_OPS_IDX: u32 = 16; @@ -133,7 +125,6 @@ pub struct rte_mempool_ops_table { pub sl: rte_spinlock_t, ///< Number of used ops structs in the table. pub num_ops: u32, - pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 56usize]>, /// Storage for all possible ops structs. pub ops: [rte_mempool_ops; 16usize], } diff --git a/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs b/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs index 0ccd40a5f8..a3a4077044 100644 --- a/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs +++ b/bindgen-tests/tests/expectations/tests/layout_large_align_field.rs @@ -1,12 +1,4 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] -#[repr(C, align(8))] -pub struct __BindgenOpaqueArray8(pub T); -impl Default for __BindgenOpaqueArray8<[T; N]> { - fn default() -> Self { - Self([::default(); N]) - } -} #[repr(C)] #[derive(Default)] pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); @@ -294,7 +286,6 @@ pub struct rte_ip_frag_tbl { pub last: *mut ip_frag_pkt, ///< LRU list for table entries. pub lru: ip_pkt_list, - pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 8usize]>, ///< statistics counters. pub stat: ip_frag_tbl_stat, ///< hash table. diff --git a/bindgen-tests/tests/expectations/tests/unknown_attr.rs b/bindgen-tests/tests/expectations/tests/unknown_attr.rs index d749dad977..5bfd121d1c 100644 --- a/bindgen-tests/tests/expectations/tests/unknown_attr.rs +++ b/bindgen-tests/tests/expectations/tests/unknown_attr.rs @@ -1,18 +1,10 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] -#[repr(C, align(8))] -pub struct __BindgenOpaqueArray8(pub T); -impl Default for __BindgenOpaqueArray8<[T; N]> { - fn default() -> Self { - Self([::default(); N]) - } -} #[repr(C)] #[repr(align(16))] #[derive(Debug, Default, Copy, Clone)] pub struct max_align_t { pub __clang_max_align_nonce1: ::std::os::raw::c_longlong, - pub __bindgen_padding_0: __BindgenOpaqueArray8<[u8; 8usize]>, + pub __bindgen_padding_0: [u8; 8usize], pub __clang_max_align_nonce2: ::std::os::raw::c_longlong, } #[allow(clippy::unnecessary_operation, clippy::identity_op)] diff --git a/bindgen-tests/tests/headers/issue-3406.h b/bindgen-tests/tests/headers/issue-3406.h new file mode 100644 index 0000000000..aa3f0c1585 --- /dev/null +++ b/bindgen-tests/tests/headers/issue-3406.h @@ -0,0 +1,8 @@ +struct __attribute__((aligned(16))) Inner { + char byte; +}; + +struct Outer { + int before; + struct Inner inner; +}; diff --git a/bindgen/codegen/struct_layout.rs b/bindgen/codegen/struct_layout.rs index 3dfd076c25..2e84304b92 100644 --- a/bindgen/codegen/struct_layout.rs +++ b/bindgen/codegen/struct_layout.rs @@ -5,7 +5,7 @@ use super::helpers; use crate::ir::comp::CompInfo; use crate::ir::context::BindgenContext; use crate::ir::layout::Layout; -use crate::ir::ty::{Type, TypeKind}; +use crate::ir::ty::Type; use crate::FieldVisibilityKind; use proc_macro2::{Ident, Span}; use std::cmp; @@ -142,27 +142,7 @@ impl<'a> StructLayoutTracker<'a> { field_ty: &Type, field_offset: Option, ) -> Option { - let mut field_layout = field_ty.layout(self.ctx)?; - - if let TypeKind::Array(inner, len) = - *field_ty.canonical_type(self.ctx).kind() - { - // FIXME(emilio): As an _ultra_ hack, we correct the layout returned - // by arrays of structs that have a bigger alignment than what we - // can support. - // - // This means that the structs in the array are super-unsafe to - // access, since they won't be properly aligned, but there's not too - // much we can do about it. - if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) - { - if layout.align > MAX_GUARANTEED_ALIGN { - field_layout.size = - align_to(layout.size, layout.align) * len; - field_layout.align = MAX_GUARANTEED_ALIGN; - } - } - } + let field_layout = field_ty.layout(self.ctx)?; self.saw_field_with_layout(field_name, field_layout, field_offset) } @@ -206,9 +186,8 @@ impl<'a> StructLayoutTracker<'a> { let force_padding = self.ctx.options().force_explicit_padding; // Otherwise the padding is useless. - let need_padding = force_padding || - padding_bytes >= field_layout.align || - field_layout.align > MAX_GUARANTEED_ALIGN; + let need_padding = + force_padding || padding_bytes >= field_layout.align; debug!( "Offset: : {} -> {}", @@ -222,12 +201,7 @@ impl<'a> StructLayoutTracker<'a> { field_offset.unwrap_or(0) / 8, ); - let padding_align = if force_padding { - 1 - } else { - cmp::min(field_layout.align, MAX_GUARANTEED_ALIGN) - }; - + let padding_align = 1; if need_padding && padding_bytes != 0 { Some(Layout::new(padding_bytes, padding_align)) } else { @@ -310,8 +284,6 @@ impl<'a> StructLayoutTracker<'a> { return None; } - let repr_align = true; - // We always pad to get to the correct size if the struct is one of // those we can't align properly. // @@ -320,8 +292,7 @@ impl<'a> StructLayoutTracker<'a> { // other fields. if padding_bytes >= layout.align || (self.last_field_was_bitfield && - padding_bytes >= self.latest_field_layout.unwrap().align) || - (!repr_align && layout.align > MAX_GUARANTEED_ALIGN) + padding_bytes >= self.latest_field_layout.unwrap().align) { let layout = if self.is_packed { Layout::new(padding_bytes, 1) @@ -343,13 +314,11 @@ impl<'a> StructLayoutTracker<'a> { } pub(crate) fn requires_explicit_align(&self, layout: Layout) -> bool { - let repr_align = true; - // Always force explicit repr(align) for stuff more than 16-byte aligned // to work-around https://github.com/rust-lang/rust/issues/54341. // // Worst-case this just generates redundant alignment attributes. - if repr_align && self.max_field_align >= 16 { + if self.max_field_align >= 16 { return true; } @@ -357,9 +326,7 @@ impl<'a> StructLayoutTracker<'a> { return false; } - // We can only generate up-to a 8-bytes of alignment unless we support - // repr(align). - repr_align || layout.align <= MAX_GUARANTEED_ALIGN + true } fn padding_bytes(&self, layout: Layout) -> usize {