Skip to content

Wrong code generated for union with bitfields #3184

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
arkeet opened this issue Apr 4, 2025 · 0 comments
Open

Wrong code generated for union with bitfields #3184

arkeet opened this issue Apr 4, 2025 · 0 comments

Comments

@arkeet
Copy link

arkeet commented Apr 4, 2025

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_b and bitfld_c use 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-gnu it 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

Full output

Generated code
Debug log

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant