diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2021-02-07 19:19:48 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2021-02-07 23:10:28 +0100 |
commit | 8ac787a9b4fab937533b964a3ee8d0bff840bf08 (patch) | |
tree | 3c69b97cfe86bf5b0f2013331509a5b237b7c097 | |
parent | 17476e9f4eee21cf7fe9aee5f5b68538bfcce169 (diff) |
codegen: Track union layout more accurately.
Instead of always generating the _bindgen_union_align method (which
shouldn't be needed at all for Rust structs, since the struct layout
tracker already deals with adding repr(align) as necessary) make sure to
visit all fields appropriately to generate the correct alignment.
41 files changed, 143 insertions, 129 deletions
diff --git a/bindgen-integration/src/lib.rs b/bindgen-integration/src/lib.rs index 0d698961..4b288afd 100755 --- a/bindgen-integration/src/lib.rs +++ b/bindgen-integration/src/lib.rs @@ -260,8 +260,6 @@ fn test_macro_customintkind_path() { assert!(v.is::<MacroInteger>()) } -// https://github.com/rust-lang/rust-bindgen/issues/1973 -#[cfg_attr(target_arch = "aarch64", should_panic)] // This line should be removed after the bug linked above is fixed #[test] fn test_homogeneous_aggregate_float_union() { unsafe { diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index cad2f47e..6a7660f6 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1219,7 +1219,7 @@ impl<'a> FieldCodegen<'a> for FieldData { ty.append_implicit_template_params(ctx, field_item); // NB: If supported, we use proper `union` types. - let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { + let ty = if parent.is_union() && !struct_layout.is_rust_union() { result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { @@ -1263,12 +1263,10 @@ impl<'a> FieldCodegen<'a> for FieldData { .expect("Each field should have a name in codegen!"); let field_ident = ctx.rust_ident_raw(field_name.as_str()); - if !parent.is_union() { - if let Some(padding_field) = - struct_layout.pad_field(&field_name, field_ty, self.offset()) - { - fields.extend(Some(padding_field)); - } + if let Some(padding_field) = + struct_layout.saw_field(&field_name, field_ty, self.offset()) + { + fields.extend(Some(padding_field)); } let is_private = (!self.is_public() && @@ -1433,7 +1431,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { let layout = self.layout(); let unit_field_ty = helpers::bitfield_unit(ctx, layout); let field_ty = { - if parent.is_union() && !parent.can_be_rust_union(ctx) { + if parent.is_union() && !struct_layout.is_rust_union() { result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { @@ -1571,7 +1569,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { _accessor_kind: FieldAccessorKind, parent: &CompInfo, _result: &mut CodegenResult, - _struct_layout: &mut StructLayoutTracker, + struct_layout: &mut StructLayoutTracker, _fields: &mut F, methods: &mut M, (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool), @@ -1612,7 +1610,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { self.is_public() && !fields_should_be_private, ); - if parent.is_union() && !parent.can_be_rust_union(ctx) { + if parent.is_union() && !struct_layout.is_rust_union() { methods.extend(Some(quote! { #[inline] #access_spec fn #getter_name(&self) -> #bitfield_ty { @@ -1768,15 +1766,53 @@ impl CodeGenerator for CompInfo { } } - let is_union = self.kind() == CompKind::Union; - let layout = item.kind().expect_type().layout(ctx); - - let mut explicit_align = None; if is_opaque { // Opaque item should not have generated methods, fields. debug_assert!(fields.is_empty()); debug_assert!(methods.is_empty()); + } + let is_union = self.kind() == CompKind::Union; + let layout = item.kind().expect_type().layout(ctx); + let zero_sized = item.is_zero_sized(ctx); + let forward_decl = self.is_forward_declaration(); + + let mut explicit_align = None; + + // C++ requires every struct to be addressable, so what C++ compilers do + // is making the struct 1-byte sized. + // + // This is apparently not the case for C, see: + // https://github.com/rust-lang/rust-bindgen/issues/551 + // + // Just get the layout, and assume C++ if not. + // + // NOTE: This check is conveniently here to avoid the dummy fields we + // may add for unused template parameters. + if !forward_decl && zero_sized { + let has_address = if is_opaque { + // Generate the address field if it's an opaque type and + // couldn't determine the layout of the blob. + layout.is_none() + } else { + layout.map_or(true, |l| l.size != 0) + }; + + if has_address { + let layout = Layout::new(1, 1); + let ty = helpers::blob(ctx, Layout::new(1, 1)); + struct_layout.saw_field_with_layout( + "_address", + layout, + /* offset = */ Some(0), + ); + fields.push(quote! { + pub _address: #ty, + }); + } + } + + if is_opaque { match layout { Some(l) => { explicit_align = Some(l.align); @@ -1790,7 +1826,7 @@ impl CodeGenerator for CompInfo { warn!("Opaque type without layout! Expect dragons!"); } } - } else if !is_union && !item.is_zero_sized(ctx) { + } else if !is_union && !zero_sized { if let Some(padding_field) = layout.and_then(|layout| struct_layout.pad_struct(layout)) { @@ -1815,57 +1851,26 @@ impl CodeGenerator for CompInfo { } } } - } else if is_union && !self.is_forward_declaration() { + } else if is_union && !forward_decl { // TODO(emilio): It'd be nice to unify this with the struct path // above somehow. let layout = layout.expect("Unable to get layout information?"); - struct_layout.saw_union(layout); - if struct_layout.requires_explicit_align(layout) { explicit_align = Some(layout.align); } - let ty = helpers::blob(ctx, layout); - fields.push(if self.can_be_rust_union(ctx) { - quote! { - _bindgen_union_align: #ty , - } - } else { - quote! { + if !struct_layout.is_rust_union() { + let ty = helpers::blob(ctx, layout); + fields.push(quote! { pub bindgen_union_field: #ty , - } - }); + }) + } } - // C++ requires every struct to be addressable, so what C++ compilers do - // is making the struct 1-byte sized. - // - // This is apparently not the case for C, see: - // https://github.com/rust-lang/rust-bindgen/issues/551 - // - // Just get the layout, and assume C++ if not. - // - // NOTE: This check is conveniently here to avoid the dummy fields we - // may add for unused template parameters. - if self.is_forward_declaration() { + if forward_decl { fields.push(quote! { _unused: [u8; 0], }); - } else if item.is_zero_sized(ctx) { - let has_address = if is_opaque { - // Generate the address field if it's an opaque type and - // couldn't determine the layout of the blob. - layout.is_none() - } else { - layout.map_or(true, |l| l.size != 0) - }; - - if has_address { - let ty = helpers::blob(ctx, Layout::new(1, 1)); - fields.push(quote! { - pub _address: #ty, - }); - } } let mut generic_param_names = vec![]; @@ -1963,7 +1968,7 @@ impl CodeGenerator for CompInfo { attributes.push(attributes::derives(&derives)) } - let mut tokens = if is_union && self.can_be_rust_union(ctx) { + let mut tokens = if is_union && struct_layout.is_rust_union() { quote! { #( #attributes )* pub union #canonical_ident diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 4536e889..2e4b9735 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -19,6 +19,7 @@ pub struct StructLayoutTracker<'a> { comp: &'a CompInfo, is_packed: bool, known_type_layout: Option<Layout>, + is_rust_union: bool, latest_offset: usize, padding_count: usize, latest_field_layout: Option<Layout>, @@ -89,12 +90,15 @@ impl<'a> StructLayoutTracker<'a> { ) -> Self { let known_type_layout = ty.layout(ctx); let is_packed = comp.is_packed(ctx, known_type_layout.as_ref()); + let is_rust_union = comp.is_union() && + comp.can_be_rust_union(ctx, known_type_layout.as_ref()); StructLayoutTracker { name, ctx, comp, is_packed, known_type_layout, + is_rust_union, latest_offset: 0, padding_count: 0, latest_field_layout: None, @@ -103,6 +107,10 @@ impl<'a> StructLayoutTracker<'a> { } } + pub fn is_rust_union(&self) -> bool { + self.is_rust_union + } + pub fn saw_vtable(&mut self) { debug!("saw vtable for {}", self.name); @@ -143,18 +151,9 @@ impl<'a> StructLayoutTracker<'a> { // actually generate the dummy alignment. } - pub fn saw_union(&mut self, layout: Layout) { - debug!("saw union for {}: {:?}", self.name, layout); - self.align_to_latest_field(layout); - - self.latest_offset += self.padding_bytes(layout) + layout.size; - self.latest_field_layout = Some(layout); - self.max_field_align = cmp::max(self.max_field_align, layout.align); - } - - /// Add a padding field if necessary for a given new field _before_ adding - /// that field. - pub fn pad_field( + /// Returns a padding field if necessary for a given new field _before_ + /// adding that field. + pub fn saw_field( &mut self, field_name: &str, field_ty: &Type, @@ -181,15 +180,27 @@ impl<'a> StructLayoutTracker<'a> { } } } + self.saw_field_with_layout(field_name, field_layout, field_offset) + } + pub fn saw_field_with_layout( + &mut self, + field_name: &str, + field_layout: Layout, + field_offset: Option<usize>, + ) -> Option<proc_macro2::TokenStream> { let will_merge_with_bitfield = self.align_to_latest_field(field_layout); + let is_union = self.comp.is_union(); let padding_bytes = match field_offset { Some(offset) if offset / 8 > self.latest_offset => { offset / 8 - self.latest_offset } _ => { - if will_merge_with_bitfield || field_layout.align == 0 { + if will_merge_with_bitfield || + field_layout.align == 0 || + is_union + { 0 } else if !self.is_packed { self.padding_bytes(field_layout) @@ -203,7 +214,7 @@ impl<'a> StructLayoutTracker<'a> { self.latest_offset += padding_bytes; - let padding_layout = if self.is_packed { + let padding_layout = if self.is_packed || is_union { None } else { // Otherwise the padding is useless. diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 60b1e2f0..52dcddd5 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1642,7 +1642,12 @@ impl CompInfo { /// Requirements: /// 1. Current RustTarget allows for `untagged_union` /// 2. Each field can derive `Copy` - pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool { + /// 3. It's not zero-sized. + pub fn can_be_rust_union( + &self, + ctx: &BindgenContext, + layout: Option<&Layout>, + ) -> bool { if !ctx.options().rust_features().untagged_union { return false; } @@ -1651,12 +1656,22 @@ impl CompInfo { return false; } - self.fields().iter().all(|f| match *f { + let all_can_copy = self.fields().iter().all(|f| match *f { Field::DataMember(ref field_data) => { field_data.ty().can_derive_copy(ctx) } Field::Bitfields(_) => true, - }) + }); + + if !all_can_copy { + return false; + } + + if layout.map_or(false, |l| l.size == 0) { + return false; + } + + true } } diff --git a/tests/expectations/tests/16-byte-alignment.rs b/tests/expectations/tests/16-byte-alignment.rs index 00d311a5..0bb92fd1 100644 --- a/tests/expectations/tests/16-byte-alignment.rs +++ b/tests/expectations/tests/16-byte-alignment.rs @@ -17,7 +17,6 @@ pub struct rte_ipv4_tuple { pub union rte_ipv4_tuple__bindgen_ty_1 { pub __bindgen_anon_1: rte_ipv4_tuple__bindgen_ty_1__bindgen_ty_1, pub sctp_tag: u32, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] @@ -159,7 +158,6 @@ pub struct rte_ipv6_tuple { pub union rte_ipv6_tuple__bindgen_ty_1 { pub __bindgen_anon_1: rte_ipv6_tuple__bindgen_ty_1__bindgen_ty_1, pub sctp_tag: u32, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] @@ -295,7 +293,6 @@ impl Default for rte_ipv6_tuple { pub union rte_thash_tuple { pub v4: rte_ipv4_tuple, pub v6: rte_ipv6_tuple, - _bindgen_union_align: [u128; 3usize], } #[test] fn bindgen_test_layout_rte_thash_tuple() { diff --git a/tests/expectations/tests/anon-fields-prefix.rs b/tests/expectations/tests/anon-fields-prefix.rs index 38baa2fd..f358dbd8 100644 --- a/tests/expectations/tests/anon-fields-prefix.rs +++ b/tests/expectations/tests/anon-fields-prefix.rs @@ -11,7 +11,6 @@ pub union color { pub u1: color__bindgen_ty_1, pub u2: color__bindgen_ty_2, pub v3: [::std::os::raw::c_uchar; 3usize], - _bindgen_union_align: [u8; 3usize], } #[repr(C)] #[derive(Debug, Default, Copy, Clone)] diff --git a/tests/expectations/tests/anon_struct_in_union.rs b/tests/expectations/tests/anon_struct_in_union.rs index 8d0035d6..008ab611 100644 --- a/tests/expectations/tests/anon_struct_in_union.rs +++ b/tests/expectations/tests/anon_struct_in_union.rs @@ -14,7 +14,6 @@ pub struct s { #[derive(Copy, Clone)] pub union s__bindgen_ty_1 { pub field: s__bindgen_ty_1_inner, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/tests/expectations/tests/anon_union.rs b/tests/expectations/tests/anon_union.rs index 02344063..386d8fad 100644 --- a/tests/expectations/tests/anon_union.rs +++ b/tests/expectations/tests/anon_union.rs @@ -35,7 +35,6 @@ pub struct TErrorResult_DOMExceptionInfo { pub union TErrorResult__bindgen_ty_1 { pub mMessage: *mut TErrorResult_Message, pub mDOMExceptionInfo: *mut TErrorResult_DOMExceptionInfo, - _bindgen_union_align: u64, } impl Default for TErrorResult__bindgen_ty_1 { fn default() -> Self { diff --git a/tests/expectations/tests/class.rs b/tests/expectations/tests/class.rs index c03f1274..b13b3c81 100644 --- a/tests/expectations/tests/class.rs +++ b/tests/expectations/tests/class.rs @@ -340,7 +340,6 @@ impl Default for IncompleteArrayNonCopiable { pub union Union { pub d: f32, pub i: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_Union() { diff --git a/tests/expectations/tests/class_with_inner_struct.rs b/tests/expectations/tests/class_with_inner_struct.rs index 8d21b674..eab54118 100644 --- a/tests/expectations/tests/class_with_inner_struct.rs +++ b/tests/expectations/tests/class_with_inner_struct.rs @@ -59,7 +59,6 @@ fn bindgen_test_layout_A_Segment() { #[derive(Copy, Clone)] pub union A__bindgen_ty_1 { pub f: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_A__bindgen_ty_1() { @@ -95,7 +94,6 @@ impl Default for A__bindgen_ty_1 { #[derive(Copy, Clone)] pub union A__bindgen_ty_2 { pub d: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_A__bindgen_ty_2() { @@ -247,7 +245,6 @@ pub struct C { pub union C__bindgen_ty_1 { pub mFunc: C__bindgen_ty_1__bindgen_ty_1, pub __bindgen_anon_1: C__bindgen_ty_1__bindgen_ty_2, - _bindgen_union_align: [u32; 4usize], } #[repr(C)] #[derive(Debug, Default, Copy, Clone, PartialEq)] diff --git a/tests/expectations/tests/derive-debug-mangle-name.rs b/tests/expectations/tests/derive-debug-mangle-name.rs index 4b4ae27b..d7f5c892 100644 --- a/tests/expectations/tests/derive-debug-mangle-name.rs +++ b/tests/expectations/tests/derive-debug-mangle-name.rs @@ -17,7 +17,6 @@ pub struct perf_event_attr { pub union perf_event_attr__bindgen_ty_1 { pub b: ::std::os::raw::c_int, pub c: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_perf_event_attr__bindgen_ty_1() { diff --git a/tests/expectations/tests/derive-partialeq-anonfield.rs b/tests/expectations/tests/derive-partialeq-anonfield.rs index 3486641d..8834ca32 100644 --- a/tests/expectations/tests/derive-partialeq-anonfield.rs +++ b/tests/expectations/tests/derive-partialeq-anonfield.rs @@ -12,9 +12,10 @@ pub struct rte_mbuf { pub __bindgen_anon_1: rte_mbuf__bindgen_ty_1, } #[repr(C)] +#[repr(align(1))] #[derive(Copy, Clone)] -pub union rte_mbuf__bindgen_ty_1 { - _bindgen_union_align: [u8; 0usize], +pub struct rte_mbuf__bindgen_ty_1 { + pub bindgen_union_field: [u8; 0usize], } #[test] fn bindgen_test_layout_rte_mbuf__bindgen_ty_1() { diff --git a/tests/expectations/tests/derive-partialeq-pointer.rs b/tests/expectations/tests/derive-partialeq-pointer.rs index 55bd782f..1964e373 100644 --- a/tests/expectations/tests/derive-partialeq-pointer.rs +++ b/tests/expectations/tests/derive-partialeq-pointer.rs @@ -41,7 +41,6 @@ pub struct c { #[repr(C)] #[derive(Copy, Clone)] pub union c__bindgen_ty_1 { - _bindgen_union_align: u8, pub _address: u8, } #[test] diff --git a/tests/expectations/tests/derive-partialeq-union.rs b/tests/expectations/tests/derive-partialeq-union.rs index e873d134..b2ccb2e8 100644 --- a/tests/expectations/tests/derive-partialeq-union.rs +++ b/tests/expectations/tests/derive-partialeq-union.rs @@ -11,7 +11,6 @@ pub union ShouldNotDerivePartialEq { pub a: ::std::os::raw::c_char, pub b: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_ShouldNotDerivePartialEq() { diff --git a/tests/expectations/tests/issue-1285.rs b/tests/expectations/tests/issue-1285.rs index 3e0da41b..4ca84527 100644 --- a/tests/expectations/tests/issue-1285.rs +++ b/tests/expectations/tests/issue-1285.rs @@ -15,7 +15,6 @@ pub struct foo { pub union foo__bindgen_ty_1 { pub a: ::std::os::raw::c_uint, pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1() { diff --git a/tests/expectations/tests/issue-1498.rs b/tests/expectations/tests/issue-1498.rs index 72bf7f7c..b14f06c8 100644 --- a/tests/expectations/tests/issue-1498.rs +++ b/tests/expectations/tests/issue-1498.rs @@ -30,7 +30,6 @@ pub union rte_memseg__bindgen_ty_1 { pub addr: *mut ::std::os::raw::c_void, ///< Makes sure addr is always 64 bits pub addr_64: u64, - _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_rte_memseg__bindgen_ty_1() { diff --git a/tests/expectations/tests/issue-493.rs b/tests/expectations/tests/issue-493.rs index 867e3d17..d17fbecc 100644 --- a/tests/expectations/tests/issue-493.rs +++ b/tests/expectations/tests/issue-493.rs @@ -84,7 +84,6 @@ pub struct basic_string___short { pub union basic_string___short__bindgen_ty_1 { pub __size_: ::std::os::raw::c_uchar, pub __lx: basic_string_value_type, - _bindgen_union_align: u8, } impl Default for basic_string___short__bindgen_ty_1 { fn default() -> Self { @@ -97,6 +96,7 @@ impl Default for basic_string___short { } } #[repr(C)] +#[repr(align(1))] pub struct basic_string___ulx { pub __lx: __BindgenUnionField<basic_string___long>, pub __lxx: __BindgenUnionField<basic_string___short>, @@ -129,6 +129,7 @@ pub struct basic_string___rep { pub __bindgen_anon_1: basic_string___rep__bindgen_ty_1, } #[repr(C)] +#[repr(align(1))] pub struct basic_string___rep__bindgen_ty_1 { pub __l: __BindgenUnionField<basic_string___long>, pub __s: __BindgenUnionField<basic_string___short>, diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs index 92ae978d..8a3d7f39 100644 --- a/tests/expectations/tests/jsval_layout_opaque.rs +++ b/tests/expectations/tests/jsval_layout_opaque.rs @@ -188,7 +188,6 @@ pub union jsval_layout { pub asPtr: *mut ::std::os::raw::c_void, pub asWord: size_t, pub asUIntPtr: usize, - _bindgen_union_align: u64, } #[repr(C)] #[repr(align(8))] @@ -271,7 +270,6 @@ pub union jsval_layout__bindgen_ty_2__bindgen_ty_1 { pub i32_: i32, pub u32_: u32, pub why: JSWhyMagic, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_jsval_layout__bindgen_ty_2__bindgen_ty_1() { diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs index 34db2c4a..fe8b92fe 100644 --- a/tests/expectations/tests/layout_eth_conf.rs +++ b/tests/expectations/tests/layout_eth_conf.rs @@ -2011,7 +2011,6 @@ pub union rte_eth_conf__bindgen_ty_2 { pub vmdq_dcb_tx_conf: rte_eth_vmdq_dcb_tx_conf, pub dcb_tx_conf: rte_eth_dcb_tx_conf, pub vmdq_tx_conf: rte_eth_vmdq_tx_conf, - _bindgen_union_align: [u32; 3usize], } #[test] fn bindgen_test_layout_rte_eth_conf__bindgen_ty_2() { diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs index a7f71a30..bc456a18 100644 --- a/tests/expectations/tests/layout_mbuf.rs +++ b/tests/expectations/tests/layout_mbuf.rs @@ -189,7 +189,6 @@ pub union rte_mbuf__bindgen_ty_1 { pub refcnt_atomic: rte_atomic16_t, ///< Non-atomically accessed refcnt pub refcnt: u16, - _bindgen_union_align: u16, } #[test] fn bindgen_test_layout_rte_mbuf__bindgen_ty_1() { @@ -241,7 +240,6 @@ pub union rte_mbuf__bindgen_ty_2 { ///< L2/L3/L4 and tunnel information. pub packet_type: u32, pub __bindgen_anon_1: rte_mbuf__bindgen_ty_2__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[repr(align(4))] @@ -449,7 +447,6 @@ pub union rte_mbuf__bindgen_ty_3 { pub sched: rte_mbuf__bindgen_ty_3__bindgen_ty_2, ///< User defined tags. See rte_distributor_process() pub usr: u32, - _bindgen_union_align: [u32; 2usize], } #[repr(C)] #[derive(Copy, Clone)] @@ -463,7 +460,6 @@ pub union rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1 { pub __bindgen_anon_1: rte_mbuf__bindgen_ty_3__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, pub lo: u32, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] @@ -686,7 +682,6 @@ pub union rte_mbuf__bindgen_ty_4 { pub userdata: *mut ::std::os::raw::c_void, ///< Allow 8-byte userdata on 32-bit pub udata64: u64, - _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_rte_mbuf__bindgen_ty_4() { @@ -738,7 +733,6 @@ pub union rte_mbuf__bindgen_ty_5 { ///< combined for easy fetch pub tx_offload: u64, pub __bindgen_anon_1: rte_mbuf__bindgen_ty_5__bindgen_ty_1, - _bindgen_union_align: u64, } #[repr(C)] #[repr(align(8))] diff --git a/tests/expectations/tests/libclang-9/class.rs b/tests/expectations/tests/libclang-9/class.rs index baa851b9..beea517e 100644 --- a/tests/expectations/tests/libclang-9/class.rs +++ b/tests/expectations/tests/libclang-9/class.rs @@ -536,7 +536,6 @@ impl Default for IncompleteArrayNonCopiable { pub union Union { pub d: f32, pub i: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_Union() { diff --git a/tests/expectations/tests/private_fields.rs b/tests/expectations/tests/private_fields.rs index f5edccae..d5371e1c 100644 --- a/tests/expectations/tests/private_fields.rs +++ b/tests/expectations/tests/private_fields.rs @@ -481,7 +481,6 @@ pub struct WithAnonUnion { #[repr(C)] #[derive(Copy, Clone)] pub union WithAnonUnion__bindgen_ty_1 { - _bindgen_union_align: u8, pub _address: u8, } #[test] diff --git a/tests/expectations/tests/struct_with_anon_union.rs b/tests/expectations/tests/struct_with_anon_union.rs index 3e0da41b..4ca84527 100644 --- a/tests/expectations/tests/struct_with_anon_union.rs +++ b/tests/expectations/tests/struct_with_anon_union.rs @@ -15,7 +15,6 @@ pub struct foo { pub union foo__bindgen_ty_1 { pub a: ::std::os::raw::c_uint, pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1() { diff --git a/tests/expectations/tests/struct_with_anon_unnamed_union.rs b/tests/expectations/tests/struct_with_anon_unnamed_union.rs index 5aeb51c3..5d03b7fb 100644 --- a/tests/expectations/tests/struct_with_anon_unnamed_union.rs +++ b/tests/expectations/tests/struct_with_anon_unnamed_union.rs @@ -15,7 +15,6 @@ pub struct foo { pub union foo__bindgen_ty_1 { pub a: ::std::os::raw::c_uint, pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1() { diff --git a/tests/expectations/tests/struct_with_nesting.rs b/tests/expectations/tests/struct_with_nesting.rs index 07583235..a98bd8ca 100644 --- a/tests/expectations/tests/struct_with_nesting.rs +++ b/tests/expectations/tests/struct_with_nesting.rs @@ -17,7 +17,6 @@ pub union foo__bindgen_ty_1 { pub b: ::std::os::raw::c_uint, pub __bindgen_anon_1: foo__bindgen_ty_1__bindgen_ty_1, pub __bindgen_anon_2: foo__bindgen_ty_1__bindgen_ty_2, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/tests/expectations/tests/typeref.rs b/tests/expectations/tests/typeref.rs index 6155ff33..b62ce929 100644 --- a/tests/expectations/tests/typeref.rs +++ b/tests/expectations/tests/typeref.rs @@ -62,7 +62,6 @@ pub struct mozilla_StyleShapeSource { pub union mozilla_StyleShapeSource__bindgen_ty_1 { pub mPosition: *mut mozilla_Position, pub mFragmentOrURL: *mut mozilla_FragmentOrURL, - _bindgen_union_align: u64, } impl Default for mozilla_StyleShapeSource__bindgen_ty_1 { fn default() -> Self { diff --git a/tests/expectations/tests/union-align.rs b/tests/expectations/tests/union-align.rs index e9c3de52..7151ba45 100644 --- a/tests/expectations/tests/union-align.rs +++ b/tests/expectations/tests/union-align.rs @@ -10,7 +10,6 @@ #[derive(Copy, Clone)] pub union Bar { pub foo: ::std::os::raw::c_uchar, - _bindgen_union_align: u128, } #[test] fn bindgen_test_layout_Bar() { @@ -35,3 +34,32 @@ impl Default for Bar { unsafe { ::std::mem::zeroed() } } } +#[repr(C)] +#[repr(align(16))] +#[derive(Copy, Clone)] +pub union Baz { + pub bar: Bar, +} +#[test] +fn bindgen_test_layout_Baz() { + assert_eq!( + ::std::mem::size_of::<Baz>(), + 16usize, + concat!("Size of: ", stringify!(Baz)) + ); + assert_eq!( + ::std::mem::align_of::<Baz>(), + 16usize, + concat!("Alignment of ", stringify!(Baz)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Baz>())).bar as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Baz), "::", stringify!(bar)) + ); +} +impl Default for Baz { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/expectations/tests/union-in-ns.rs b/tests/expectations/tests/union-in-ns.rs index 2ff76bb8..abb330b8 100644 --- a/tests/expectations/tests/union-in-ns.rs +++ b/tests/expectations/tests/union-in-ns.rs @@ -13,7 +13,6 @@ pub mod root { #[derive(Copy, Clone)] pub union bar { pub baz: ::std::os::raw::c_int, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_bar() { diff --git a/tests/expectations/tests/union_bitfield.rs b/tests/expectations/tests/union_bitfield.rs index 22c0de85..cf3595ec 100644 --- a/tests/expectations/tests/union_bitfield.rs +++ b/tests/expectations/tests/union_bitfield.rs @@ -92,11 +92,11 @@ where } } #[repr(C)] +#[repr(align(4))] #[derive(Copy, Clone)] pub union U4 { pub _bitfield_align_1: [u8; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_U4() { @@ -144,11 +144,11 @@ impl U4 { } } #[repr(C)] +#[repr(align(4))] #[derive(Copy, Clone)] pub union B { pub _bitfield_align_1: [u32; 0], pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_B() { diff --git a/tests/expectations/tests/union_dtor.rs b/tests/expectations/tests/union_dtor.rs index dd3635e1..a06e8ccf 100644 --- a/tests/expectations/tests/union_dtor.rs +++ b/tests/expectations/tests/union_dtor.rs @@ -9,7 +9,6 @@ pub union UnionWithDtor { pub mFoo: ::std::os::raw::c_int, pub mBar: *mut ::std::os::raw::c_void, - _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_UnionWithDtor() { diff --git a/tests/expectations/tests/union_fields.rs b/tests/expectations/tests/union_fields.rs index d0bc26c2..e605b0bc 100644 --- a/tests/expectations/tests/union_fields.rs +++ b/tests/expectations/tests/union_fields.rs @@ -11,7 +11,6 @@ pub union nsStyleUnion { pub mInt: ::std::os::raw::c_int, pub mFloat: f32, pub mPointer: *mut ::std::os::raw::c_void, - _bindgen_union_align: u64, } #[test] fn bindgen_test_layout_nsStyleUnion() { diff --git a/tests/expectations/tests/union_template.rs b/tests/expectations/tests/union_template.rs index fcef30c9..6a366f9e 100644 --- a/tests/expectations/tests/union_template.rs +++ b/tests/expectations/tests/union_template.rs @@ -15,7 +15,6 @@ pub struct NastyStruct { pub union NastyStruct__bindgen_ty_1 { pub mFoo: *mut ::std::os::raw::c_void, pub mDummy: ::std::os::raw::c_ulong, - _bindgen_union_align: u64, } impl Default for NastyStruct__bindgen_ty_1 { fn default() -> Self { @@ -26,7 +25,6 @@ impl Default for NastyStruct__bindgen_ty_1 { pub union NastyStruct__bindgen_ty_2 { pub wat: ::std::os::raw::c_short, pub wut: *mut ::std::os::raw::c_int, - _bindgen_union_align: u64, } impl Default for NastyStruct__bindgen_ty_2 { fn default() -> Self { @@ -42,7 +40,6 @@ impl Default for NastyStruct { pub union Whatever { pub mTPtr: *mut ::std::os::raw::c_void, pub mInt: ::std::os::raw::c_int, - _bindgen_union_align: u64, } impl Default for Whatever { fn default() -> Self { diff --git a/tests/expectations/tests/union_with_anon_struct.rs b/tests/expectations/tests/union_with_anon_struct.rs index 8113ae09..7d061cec 100644 --- a/tests/expectations/tests/union_with_anon_struct.rs +++ b/tests/expectations/tests/union_with_anon_struct.rs @@ -9,7 +9,6 @@ #[derive(Copy, Clone)] pub union foo { pub bar: foo__bindgen_ty_1, - _bindgen_union_align: [u32; 2usize], } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/tests/expectations/tests/union_with_anon_struct_bitfield.rs index 445a97ef..2e3e6415 100644 --- a/tests/expectations/tests/union_with_anon_struct_bitfield.rs +++ b/tests/expectations/tests/union_with_anon_struct_bitfield.rs @@ -96,7 +96,6 @@ where pub union foo { pub a: ::std::os::raw::c_int, pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[repr(align(4))] diff --git a/tests/expectations/tests/union_with_anon_union.rs b/tests/expectations/tests/union_with_anon_union.rs index 89756d44..83e4801a 100644 --- a/tests/expectations/tests/union_with_anon_union.rs +++ b/tests/expectations/tests/union_with_anon_union.rs @@ -9,14 +9,12 @@ #[derive(Copy, Clone)] pub union foo { pub bar: foo__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Copy, Clone)] pub union foo__bindgen_ty_1 { pub a: ::std::os::raw::c_uint, pub b: ::std::os::raw::c_ushort, - _bindgen_union_align: u32, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1() { diff --git a/tests/expectations/tests/union_with_anon_unnamed_struct.rs b/tests/expectations/tests/union_with_anon_unnamed_struct.rs index 7f1d794f..5802f563 100644 --- a/tests/expectations/tests/union_with_anon_unnamed_struct.rs +++ b/tests/expectations/tests/union_with_anon_unnamed_struct.rs @@ -10,7 +10,6 @@ pub union pixel { pub rgba: ::std::os::raw::c_uint, pub __bindgen_anon_1: pixel__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/tests/expectations/tests/union_with_anon_unnamed_union.rs b/tests/expectations/tests/union_with_anon_unnamed_union.rs index 1720b82f..fc465737 100644 --- a/tests/expectations/tests/union_with_anon_unnamed_union.rs +++ b/tests/expectations/tests/union_with_anon_unnamed_union.rs @@ -10,14 +10,12 @@ pub union foo { pub a: ::std::os::raw::c_uint, pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Copy, Clone)] pub union foo__bindgen_ty_1 { pub b: ::std::os::raw::c_ushort, pub c: ::std::os::raw::c_uchar, - _bindgen_union_align: u16, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1() { diff --git a/tests/expectations/tests/union_with_big_member.rs b/tests/expectations/tests/union_with_big_member.rs index ebfe7656..6425c114 100644 --- a/tests/expectations/tests/union_with_big_member.rs +++ b/tests/expectations/tests/union_with_big_member.rs @@ -10,7 +10,6 @@ pub union WithBigArray { pub a: ::std::os::raw::c_int, pub b: [::std::os::raw::c_int; 33usize], - _bindgen_union_align: [u32; 33usize], } #[test] fn bindgen_test_layout_WithBigArray() { @@ -59,7 +58,6 @@ impl Default for WithBigArray { pub union WithBigArray2 { pub a: ::std::os::raw::c_int, pub b: [::std::os::raw::c_char; 33usize], - _bindgen_union_align: [u32; 9usize], } #[test] fn bindgen_test_layout_WithBigArray2() { @@ -108,7 +106,6 @@ impl Default for WithBigArray2 { pub union WithBigMember { pub a: ::std::os::raw::c_int, pub b: WithBigArray, - _bindgen_union_align: [u32; 33usize], } #[test] fn bindgen_test_layout_WithBigMember() { diff --git a/tests/expectations/tests/union_with_nesting.rs b/tests/expectations/tests/union_with_nesting.rs index c1403d2c..55045f2f 100644 --- a/tests/expectations/tests/union_with_nesting.rs +++ b/tests/expectations/tests/union_with_nesting.rs @@ -10,7 +10,6 @@ pub union foo { pub a: ::std::os::raw::c_uint, pub __bindgen_anon_1: foo__bindgen_ty_1, - _bindgen_union_align: u32, } #[repr(C)] #[derive(Copy, Clone)] @@ -23,7 +22,6 @@ pub struct foo__bindgen_ty_1 { pub union foo__bindgen_ty_1__bindgen_ty_1 { pub b1: ::std::os::raw::c_ushort, pub b2: ::std::os::raw::c_ushort, - _bindgen_union_align: u16, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_1() { @@ -74,7 +72,6 @@ impl Default for foo__bindgen_ty_1__bindgen_ty_1 { pub union foo__bindgen_ty_1__bindgen_ty_2 { pub c1: ::std::os::raw::c_ushort, pub c2: ::std::os::raw::c_ushort, - _bindgen_union_align: u16, } #[test] fn bindgen_test_layout_foo__bindgen_ty_1__bindgen_ty_2() { diff --git a/tests/expectations/tests/use-core.rs b/tests/expectations/tests/use-core.rs index 89c631eb..4cb2851f 100644 --- a/tests/expectations/tests/use-core.rs +++ b/tests/expectations/tests/use-core.rs @@ -52,7 +52,6 @@ impl Default for foo { pub union _bindgen_ty_1 { pub bar: ::std::os::raw::c_int, pub baz: ::std::os::raw::c_long, - _bindgen_union_align: u64, } #[test] fn bindgen_test_layout__bindgen_ty_1() { diff --git a/tests/headers/union-align.h b/tests/headers/union-align.h index 94e60ef1..9557b279 100644 --- a/tests/headers/union-align.h +++ b/tests/headers/union-align.h @@ -3,3 +3,8 @@ union Bar { unsigned char foo; } __attribute__ ((__aligned__ (16))); + + +union Baz { + union Bar bar; +}; |