rust-bindgen
rust-bindgen copied to clipboard
Wrong code generated for union with bitfields
The below outputs are with bindgen 0.71.1 (no flags) on x86_64-pc-windows-msvc.
Consider the union below. There are two issues:
- The accessors for
bitfld_bandbitfld_cuse bit offsets of 4 and 8, respectively, while they should be 0. - The generated type has the wrong size, resulting in a compile error. The C type has size 4 and alignment 1, but the generated type has size 2. (On
x86_64-unknown-linux-gnuit happens to compile(!) because the alignment is 4 which makes the size also 4.) Therefore, padding needs to be added.
Don't ask me why someone put a bitfield in a union. (The case I found was an anonymous union in a struct, but that doesn't seem to make a difference.)
Header file
union Union {
int bitfld_a : 4;
int bitfld_b : 4;
int bitfld_c : 4;
};
Generated code (excerpt)
#[repr(C)]
#[derive(Copy, Clone)]
pub union Union {
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>,
// ^^^^^^ should be 4usize
}
#[allow(clippy::unnecessary_operation, clippy::identity_op)]
const _: () = {
["Size of Union"][::std::mem::size_of::<Union>() - 4usize];
["Alignment of Union"][::std::mem::align_of::<Union>() - 1usize];
};
impl Union {
// ...
pub fn bitfld_b(&self) -> ::std::os::raw::c_int {
unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u32) }
// ^^^^^^ should be 0usize
}
// ...
}
Compile error
error[E0080]: evaluation of constant value failed
--> bindings.rs:148:23
|
148 | ["Size of Union"][::std::mem::size_of::<Union>() - 4usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `2_usize - 4_usize`, which would overflow