summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-10-09 19:28:44 -0500
committerGitHub <noreply@github.com>2017-10-09 19:28:44 -0500
commit5dbdadc5cc1d15e23d804b4d0ce80cae90338ef7 (patch)
tree037a4ef445842ae2cd4598accc89e1e4774503ce
parent745d60610ec6979368fc240472f7c04a3e04f282 (diff)
parentc187b9f36001bebf756f9ed4748deeb01759c61b (diff)
Auto merge of #1066 - pepyakin:bitfields-in-unions, r=fitzgen
Bitfields in unions Fixes #744 I think it is WIP for the moment as I didn't run tests locally.
-rw-r--r--src/codegen/mod.rs16
-rw-r--r--src/ir/comp.rs2
-rw-r--r--tests/expectations/tests/union_bitfield.rs185
-rw-r--r--tests/expectations/tests/union_bitfield_1_0.rs242
-rw-r--r--tests/headers/union_bitfield.h10
-rw-r--r--tests/headers/union_bitfield_1_0.h14
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;
+};