Skip to content

Commit c187b9f

Browse files
committed
Fix bitfields in bindgen unions
1 parent bfd5030 commit c187b9f

File tree

3 files changed

+271
-1
lines changed

3 files changed

+271
-1
lines changed

src/codegen/mod.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -1152,7 +1152,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
11521152
F: Extend<quote::Tokens>,
11531153
M: Extend<quote::Tokens>,
11541154
{
1155-
let field_ty = helpers::blob(self.layout());
1155+
let field_ty = if parent.is_union() && !parent.can_be_rust_union(ctx) {
1156+
let ty = helpers::blob(self.layout());
1157+
if ctx.options().enable_cxx_namespaces {
1158+
quote! {
1159+
root::__BindgenUnionField<#ty>
1160+
}
1161+
} else {
1162+
quote! {
1163+
__BindgenUnionField<#ty>
1164+
}
1165+
}
1166+
} else {
1167+
helpers::blob(self.layout())
1168+
};
1169+
11561170
let unit_field_name = format!("_bitfield_{}", self.nth());
11571171
let unit_field_ident = ctx.rust_ident(&unit_field_name);
11581172

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
7+
#[repr(C)]
8+
pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>);
9+
impl<T> __BindgenUnionField<T> {
10+
#[inline]
11+
pub fn new() -> Self {
12+
__BindgenUnionField(::std::marker::PhantomData)
13+
}
14+
#[inline]
15+
pub unsafe fn as_ref(&self) -> &T {
16+
::std::mem::transmute(self)
17+
}
18+
#[inline]
19+
pub unsafe fn as_mut(&mut self) -> &mut T {
20+
::std::mem::transmute(self)
21+
}
22+
}
23+
impl<T> ::std::default::Default for __BindgenUnionField<T> {
24+
#[inline]
25+
fn default() -> Self {
26+
Self::new()
27+
}
28+
}
29+
impl<T> ::std::clone::Clone for __BindgenUnionField<T> {
30+
#[inline]
31+
fn clone(&self) -> Self {
32+
Self::new()
33+
}
34+
}
35+
impl<T> ::std::marker::Copy for __BindgenUnionField<T> {}
36+
impl<T> ::std::fmt::Debug for __BindgenUnionField<T> {
37+
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
38+
fmt.write_str("__BindgenUnionField")
39+
}
40+
}
41+
impl<T> ::std::hash::Hash for __BindgenUnionField<T> {
42+
fn hash<H: ::std::hash::Hasher>(&self, _state: &mut H) {}
43+
}
44+
impl<T> ::std::cmp::PartialEq for __BindgenUnionField<T> {
45+
fn eq(&self, _other: &__BindgenUnionField<T>) -> bool {
46+
true
47+
}
48+
}
49+
impl<T> ::std::cmp::Eq for __BindgenUnionField<T> {}
50+
#[repr(C)]
51+
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
52+
pub struct U4 {
53+
pub _bitfield_1: __BindgenUnionField<u8>,
54+
pub bindgen_union_field: u32,
55+
}
56+
#[test]
57+
fn bindgen_test_layout_U4() {
58+
assert_eq!(
59+
::std::mem::size_of::<U4>(),
60+
4usize,
61+
concat!("Size of: ", stringify!(U4))
62+
);
63+
assert_eq!(
64+
::std::mem::align_of::<U4>(),
65+
4usize,
66+
concat!("Alignment of ", stringify!(U4))
67+
);
68+
}
69+
impl Clone for U4 {
70+
fn clone(&self) -> Self {
71+
*self
72+
}
73+
}
74+
impl U4 {
75+
#[inline]
76+
pub fn derp(&self) -> ::std::os::raw::c_uint {
77+
let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() };
78+
unsafe {
79+
::std::ptr::copy_nonoverlapping(
80+
&self._bitfield_1 as *const _ as *const u8,
81+
&mut unit_field_val as *mut u8 as *mut u8,
82+
::std::mem::size_of::<u8>(),
83+
)
84+
};
85+
let mask = 1u64 as u8;
86+
let val = (unit_field_val & mask) >> 0usize;
87+
unsafe { ::std::mem::transmute(val as u32) }
88+
}
89+
#[inline]
90+
pub fn set_derp(&mut self, val: ::std::os::raw::c_uint) {
91+
let mask = 1u64 as u8;
92+
let val = val as u32 as u8;
93+
let mut unit_field_val: u8 = unsafe { ::std::mem::uninitialized() };
94+
unsafe {
95+
::std::ptr::copy_nonoverlapping(
96+
&self._bitfield_1 as *const _ as *const u8,
97+
&mut unit_field_val as *mut u8 as *mut u8,
98+
::std::mem::size_of::<u8>(),
99+
)
100+
};
101+
unit_field_val &= !mask;
102+
unit_field_val |= (val << 0usize) & mask;
103+
unsafe {
104+
::std::ptr::copy_nonoverlapping(
105+
&unit_field_val as *const _ as *const u8,
106+
&mut self._bitfield_1 as *mut _ as *mut u8,
107+
::std::mem::size_of::<u8>(),
108+
);
109+
}
110+
}
111+
#[inline]
112+
pub fn new_bitfield_1(derp: ::std::os::raw::c_uint) -> u8 {
113+
(0 | ((derp as u32 as u8) << 0usize) & (1u64 as u8))
114+
}
115+
}
116+
#[repr(C)]
117+
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
118+
pub struct B {
119+
pub _bitfield_1: __BindgenUnionField<u32>,
120+
pub bindgen_union_field: u32,
121+
}
122+
#[test]
123+
fn bindgen_test_layout_B() {
124+
assert_eq!(
125+
::std::mem::size_of::<B>(),
126+
4usize,
127+
concat!("Size of: ", stringify!(B))
128+
);
129+
assert_eq!(
130+
::std::mem::align_of::<B>(),
131+
4usize,
132+
concat!("Alignment of ", stringify!(B))
133+
);
134+
}
135+
impl Clone for B {
136+
fn clone(&self) -> Self {
137+
*self
138+
}
139+
}
140+
impl B {
141+
#[inline]
142+
pub fn foo(&self) -> ::std::os::raw::c_uint {
143+
let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() };
144+
unsafe {
145+
::std::ptr::copy_nonoverlapping(
146+
&self._bitfield_1 as *const _ as *const u8,
147+
&mut unit_field_val as *mut u32 as *mut u8,
148+
::std::mem::size_of::<u32>(),
149+
)
150+
};
151+
let mask = 2147483647u64 as u32;
152+
let val = (unit_field_val & mask) >> 0usize;
153+
unsafe { ::std::mem::transmute(val as u32) }
154+
}
155+
#[inline]
156+
pub fn set_foo(&mut self, val: ::std::os::raw::c_uint) {
157+
let mask = 2147483647u64 as u32;
158+
let val = val as u32 as u32;
159+
let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() };
160+
unsafe {
161+
::std::ptr::copy_nonoverlapping(
162+
&self._bitfield_1 as *const _ as *const u8,
163+
&mut unit_field_val as *mut u32 as *mut u8,
164+
::std::mem::size_of::<u32>(),
165+
)
166+
};
167+
unit_field_val &= !mask;
168+
unit_field_val |= (val << 0usize) & mask;
169+
unsafe {
170+
::std::ptr::copy_nonoverlapping(
171+
&unit_field_val as *const _ as *const u8,
172+
&mut self._bitfield_1 as *mut _ as *mut u8,
173+
::std::mem::size_of::<u32>(),
174+
);
175+
}
176+
}
177+
#[inline]
178+
pub fn bar(&self) -> ::std::os::raw::c_uchar {
179+
let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() };
180+
unsafe {
181+
::std::ptr::copy_nonoverlapping(
182+
&self._bitfield_1 as *const _ as *const u8,
183+
&mut unit_field_val as *mut u32 as *mut u8,
184+
::std::mem::size_of::<u32>(),
185+
)
186+
};
187+
let mask = 2147483648u64 as u32;
188+
let val = (unit_field_val & mask) >> 31usize;
189+
unsafe { ::std::mem::transmute(val as u8) }
190+
}
191+
#[inline]
192+
pub fn set_bar(&mut self, val: ::std::os::raw::c_uchar) {
193+
let mask = 2147483648u64 as u32;
194+
let val = val as u8 as u32;
195+
let mut unit_field_val: u32 = unsafe { ::std::mem::uninitialized() };
196+
unsafe {
197+
::std::ptr::copy_nonoverlapping(
198+
&self._bitfield_1 as *const _ as *const u8,
199+
&mut unit_field_val as *mut u32 as *mut u8,
200+
::std::mem::size_of::<u32>(),
201+
)
202+
};
203+
unit_field_val &= !mask;
204+
unit_field_val |= (val << 31usize) & mask;
205+
unsafe {
206+
::std::ptr::copy_nonoverlapping(
207+
&unit_field_val as *const _ as *const u8,
208+
&mut self._bitfield_1 as *mut _ as *mut u8,
209+
::std::mem::size_of::<u32>(),
210+
);
211+
}
212+
}
213+
#[inline]
214+
pub fn new_bitfield_1(foo: ::std::os::raw::c_uint, bar: ::std::os::raw::c_uchar) -> u32 {
215+
((0 | ((foo as u32 as u32) << 0usize) & (2147483647u64 as u32))
216+
| ((bar as u8 as u32) << 31usize) & (2147483648u64 as u32))
217+
}
218+
}
219+
#[repr(C)]
220+
#[derive(Copy)]
221+
pub struct HasBigBitfield {
222+
pub _bitfield_1: __BindgenUnionField<[u8; 16usize]>,
223+
pub bindgen_union_field: [u8; 16usize],
224+
}
225+
#[test]
226+
fn bindgen_test_layout_HasBigBitfield() {
227+
assert_eq!(
228+
::std::mem::size_of::<HasBigBitfield>(),
229+
16usize,
230+
concat!("Size of: ", stringify!(HasBigBitfield))
231+
);
232+
}
233+
impl Clone for HasBigBitfield {
234+
fn clone(&self) -> Self {
235+
*self
236+
}
237+
}
238+
impl Default for HasBigBitfield {
239+
fn default() -> Self {
240+
unsafe { ::std::mem::zeroed() }
241+
}
242+
}

tests/headers/union_bitfield_1_0.h

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// bindgen-flags: --rust-target 1.0 --with-derive-hash --with-derive-partialeq --with-derive-eq --impl-partialeq
2+
3+
union U4 {
4+
unsigned derp : 1;
5+
};
6+
7+
union B {
8+
unsigned foo : 31;
9+
unsigned char bar : 1;
10+
};
11+
12+
union HasBigBitfield {
13+
__int128 x : 128;
14+
};

0 commit comments

Comments
 (0)