Input C/C++ Header
_BitInt(24) f(_BitInt(24) v);
Bindgen Invocation
Actual Results
extern "C" {
pub fn f(v: u32) -> u32;
}
Expected Results
A signed type, or an error.
_BitInt looks unhandled: libclang reports it as CXType_Unexposed, so it ends up in the opaque blob fallback, which picks a type by size from a table that only has unsigned integers in it. So every signed _BitInt(N) comes out unsigned, and widths that aren't a whole storage unit get widened — _BitInt(7) → u8, _BitInt(24) → u32, _BitInt(33) → u64. An extern _BitInt(24) x; declaration is dropped from the output entirely.
The widening isn't only cosmetic, because a sub-storage-width _BitInt carries an extension contract on x86-64. clang emits
declare signext i24 @f(i24 noundef signext)
while the binding lowers to a plain i32, so Rust reads bits that the ABI defines as sign extension. Calling f(0x7FFFFF) (increment the largest positive 24-bit value) returns -8388608 from C and 4286578688 through the binding. Nothing is printed on the way.
One thing worth not changing: unsigned _BitInt(128) currently maps to __BindgenOpaqueArray<u64, 2> and that's already correct — x86-64 gives _BitInt(128) alignment 8 rather than __int128's 16, and rust-lang/rust#137306 says i128 won't be guaranteed to match it.
$ bindgen --version
bindgen 0.72.1
$ clang --version
Ubuntu clang version 15.0.7
$ rustc --version
rustc 1.75.0
Target is x86_64-unknown-linux-gnu.
Input C/C++ Header
Bindgen Invocation
Actual Results
Expected Results
A signed type, or an error.
_BitIntlooks unhandled: libclang reports it asCXType_Unexposed, so it ends up in the opaque blob fallback, which picks a type by size from a table that only has unsigned integers in it. So every signed_BitInt(N)comes out unsigned, and widths that aren't a whole storage unit get widened —_BitInt(7)→u8,_BitInt(24)→u32,_BitInt(33)→u64. Anextern _BitInt(24) x;declaration is dropped from the output entirely.The widening isn't only cosmetic, because a sub-storage-width
_BitIntcarries an extension contract on x86-64. clang emitswhile the binding lowers to a plain
i32, so Rust reads bits that the ABI defines as sign extension. Callingf(0x7FFFFF)(increment the largest positive 24-bit value) returns-8388608from C and4286578688through the binding. Nothing is printed on the way.One thing worth not changing:
unsigned _BitInt(128)currently maps to__BindgenOpaqueArray<u64, 2>and that's already correct — x86-64 gives_BitInt(128)alignment 8 rather than__int128's 16, and rust-lang/rust#137306 saysi128won't be guaranteed to match it.Target is
x86_64-unknown-linux-gnu.