diff options
-rw-r--r-- | src/codegen/mod.rs | 16 | ||||
-rw-r--r-- | src/ir/comp.rs | 2 | ||||
-rw-r--r-- | tests/expectations/tests/union_bitfield.rs | 185 | ||||
-rw-r--r-- | tests/expectations/tests/union_bitfield_1_0.rs | 242 | ||||
-rw-r--r-- | tests/headers/union_bitfield.h | 10 | ||||
-rw-r--r-- | tests/headers/union_bitfield_1_0.h | 14 |
6 files changed, 467 insertions, 2 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index ea9fec41..94a62b97 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1152,7 +1152,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { F: Extend<quote::Tokens>, M: Extend<quote::Tokens>, { - let field_ty = helpers::blob(self.layout()); + let field_ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { + let ty = helpers::blob(self.layout()); + if ctx.options().enable_cxx_namespaces { + quote! { + root::__BindgenUnionField<#ty> + } + } else { + quote! { + __BindgenUnionField<#ty> + } + } + } else { + helpers::blob(self.layout()) + }; + let unit_field_name = format!("_bitfield_{}", self.nth()); let unit_field_ident = ctx.rust_ident(&unit_field_name); diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 230ba5b4..7320015f 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1498,7 +1498,7 @@ impl CompInfo { Field::DataMember(ref field_data) => { field_data.ty().can_derive_copy(ctx) } - Field::Bitfields(_) => false, + Field::Bitfields(_) => true, }) } } diff --git a/tests/expectations/tests/union_bitfield.rs b/tests/expectations/tests/union_bitfield.rs new file mode 100644 index 00000000..c67557ef --- /dev/null +++ b/tests/expectations/tests/union_bitfield.rs @@ -0,0 +1,185 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Copy)] +pub union U4 { + pub _bitfield_1: u8, + _bindgen_union_align: u32, +} +#[test] +fn bindgen_test_layout_U4() { + assert_eq!( + ::std::mem::size_of::<U4>(), + 4usize, + concat!("Size of: ", stringify!(U4)) + ); + assert_eq!( + ::std::mem::align_of::<U4>(), + 4usize, + concat!("Alignment of ", stringify!(U4)) + ); +} +impl Clone for U4 { + fn clone(&self) -> Self { + *self + } +} +impl Default for U4 { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +impl U4 { + #[inline] + pub fn derp(&self) -> ::std::os::raw::c_uint { + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u8 as *mut u8, + ::std::mem::size_of::<u8>(), + ) + }; + let mask = 1u64 as u8; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u32) } + } + #[inline] + pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) { + let mask = 1u64 as u8; + let val = val as u32 as u8; + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u8 as *mut u8, + ::std::mem::size_of::<u8>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u8>(), + ); + } + } + #[inline] + pub fn new_bitfield_1(derp: ::std::os::raw::c_uint) -> u8 { + (0 | ((derp as u32 as u8) << 0usize) & (1u64 as u8)) + } +} +#[repr(C)] +#[derive(Copy)] +pub union B { + pub _bitfield_1: u32, + _bindgen_union_align: u32, +} +#[test] +fn bindgen_test_layout_B() { + assert_eq!( + ::std::mem::size_of::<B>(), + 4usize, + concat!("Size of: ", stringify!(B)) + ); + assert_eq!( + ::std::mem::align_of::<B>(), + 4usize, + concat!("Alignment of ", stringify!(B)) + ); +} +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} +impl Default for B { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +impl B { + #[inline] + pub fn foo(&self) -> ::std::os::raw::c_uint { + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + let mask = 2147483647u64 as u32; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u32) } + } + #[inline] + pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { + let mask = 2147483647u64 as u32; + let val = val as u32 as u32; + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u32>(), + ); + } + } + #[inline] + pub fn bar(&self) -> ::std::os::raw::c_uchar { + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + let mask = 2147483648u64 as u32; + let val = (unit_field_val & mask) >> 31usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { + let mask = 2147483648u64 as u32; + let val = val as u8 as u32; + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 31usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u32>(), + ); + } + } + #[inline] + pub fn new_bitfield_1(foo: ::std::os::raw::c_uint, bar: ::std::os::raw::c_uchar) -> u32 { + ((0 | ((foo as u32 as u32) << 0usize) & (2147483647u64 as u32)) + | ((bar as u8 as u32) << 31usize) & (2147483648u64 as u32)) + } +} diff --git a/tests/expectations/tests/union_bitfield_1_0.rs b/tests/expectations/tests/union_bitfield_1_0.rs new file mode 100644 index 00000000..d8fe660c --- /dev/null +++ b/tests/expectations/tests/union_bitfield_1_0.rs @@ -0,0 +1,242 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); +impl<T> __BindgenUnionField<T> { + #[inline] + pub fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } +} +impl<T> ::std::default::Default for __BindgenUnionField<T> { + #[inline] + fn default() -> Self { + Self::new() + } +} +impl<T> ::std::clone::Clone for __BindgenUnionField<T> { + #[inline] + fn clone(&self) -> Self { + Self::new() + } +} +impl<T> ::std::marker::Copy for __BindgenUnionField<T> {} +impl<T> ::std::fmt::Debug for __BindgenUnionField<T> { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } +} +impl<T> ::std::hash::Hash for __BindgenUnionField<T> { + fn hash<H: ::std::hash::Hasher>(&self, _state: &mut H) {} +} +impl<T> ::std::cmp::PartialEq for __BindgenUnionField<T> { + fn eq(&self, _other: &__BindgenUnionField<T>) -> bool { + true + } +} +impl<T> ::std::cmp::Eq for __BindgenUnionField<T> {} +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] +pub struct U4 { + pub _bitfield_1: __BindgenUnionField<u8>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_U4() { + assert_eq!( + ::std::mem::size_of::<U4>(), + 4usize, + concat!("Size of: ", stringify!(U4)) + ); + assert_eq!( + ::std::mem::align_of::<U4>(), + 4usize, + concat!("Alignment of ", stringify!(U4)) + ); +} +impl Clone for U4 { + fn clone(&self) -> Self { + *self + } +} +impl U4 { + #[inline] + pub fn derp(&self) -> ::std::os::raw::c_uint { + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u8 as *mut u8, + ::std::mem::size_of::<u8>(), + ) + }; + let mask = 1u64 as u8; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u32) } + } + #[inline] + pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) { + let mask = 1u64 as u8; + let val = val as u32 as u8; + let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u8 as *mut u8, + ::std::mem::size_of::<u8>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u8>(), + ); + } + } + #[inline] + pub fn new_bitfield_1(derp: ::std::os::raw::c_uint) -> u8 { + (0 | ((derp as u32 as u8) << 0usize) & (1u64 as u8)) + } +} +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] +pub struct B { + pub _bitfield_1: __BindgenUnionField<u32>, + pub bindgen_union_field: u32, +} +#[test] +fn bindgen_test_layout_B() { + assert_eq!( + ::std::mem::size_of::<B>(), + 4usize, + concat!("Size of: ", stringify!(B)) + ); + assert_eq!( + ::std::mem::align_of::<B>(), + 4usize, + concat!("Alignment of ", stringify!(B)) + ); +} +impl Clone for B { + fn clone(&self) -> Self { + *self + } +} +impl B { + #[inline] + pub fn foo(&self) -> ::std::os::raw::c_uint { + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + let mask = 2147483647u64 as u32; + let val = (unit_field_val & mask) >> 0usize; + unsafe { ::std::mem::transmute(val as u32) } + } + #[inline] + pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) { + let mask = 2147483647u64 as u32; + let val = val as u32 as u32; + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 0usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u32>(), + ); + } + } + #[inline] + pub fn bar(&self) -> ::std::os::raw::c_uchar { + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + let mask = 2147483648u64 as u32; + let val = (unit_field_val & mask) >> 31usize; + unsafe { ::std::mem::transmute(val as u8) } + } + #[inline] + pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) { + let mask = 2147483648u64 as u32; + let val = val as u8 as u32; + let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() }; + unsafe { + ::std::ptr::copy_nonoverlapping( + &self._bitfield_1 as *const _ as *const u8, + &mut unit_field_val as *mut u32 as *mut u8, + ::std::mem::size_of::<u32>(), + ) + }; + unit_field_val &= !mask; + unit_field_val |= (val << 31usize) & mask; + unsafe { + ::std::ptr::copy_nonoverlapping( + &unit_field_val as *const _ as *const u8, + &mut self._bitfield_1 as *mut _ as *mut u8, + ::std::mem::size_of::<u32>(), + ); + } + } + #[inline] + pub fn new_bitfield_1(foo: ::std::os::raw::c_uint, bar: ::std::os::raw::c_uchar) -> u32 { + ((0 | ((foo as u32 as u32) << 0usize) & (2147483647u64 as u32)) + | ((bar as u8 as u32) << 31usize) & (2147483648u64 as u32)) + } +} +#[repr(C)] +#[derive(Copy)] +pub struct HasBigBitfield { + pub _bitfield_1: __BindgenUnionField<[u8; 16usize]>, + pub bindgen_union_field: [u8; 16usize], +} +#[test] +fn bindgen_test_layout_HasBigBitfield() { + assert_eq!( + ::std::mem::size_of::<HasBigBitfield>(), + 16usize, + concat!("Size of: ", stringify!(HasBigBitfield)) + ); +} +impl Clone for HasBigBitfield { + fn clone(&self) -> Self { + *self + } +} +impl Default for HasBigBitfield { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/headers/union_bitfield.h b/tests/headers/union_bitfield.h new file mode 100644 index 00000000..99072957 --- /dev/null +++ b/tests/headers/union_bitfield.h @@ -0,0 +1,10 @@ +// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq + +union U4 { + unsigned derp : 1; +}; + +union B { + unsigned foo : 31; + unsigned char bar : 1; +}; diff --git a/tests/headers/union_bitfield_1_0.h b/tests/headers/union_bitfield_1_0.h new file mode 100644 index 00000000..06b61ad7 --- /dev/null +++ b/tests/headers/union_bitfield_1_0.h @@ -0,0 +1,14 @@ +// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq + +union U4 { + unsigned derp : 1; +}; + +union B { + unsigned foo : 31; + unsigned char bar : 1; +}; + +union HasBigBitfield { + __int128 x : 128; +}; |