rust-lang / rust-lang/rust-bindgen

`_BitInt` types lose their signedness and get widened to the next storage size

Open
#3,398 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Input C/C++ Header
_BitInt(24) f(_BitInt(24) v);
Bindgen Invocation
$ bindgen input.h
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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing how CXType_Unexposed types enter the opaque blob fallback when bindgen processes the shown input.h declaration. Compare signed and unsigned _BitInt results, including the dropped extern variable, by running bindgen on the reproducer. Done means signedness and widths are preserved or an error is reported, without changing the existing unsigned _BitInt(128) mapping.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp, rust
Domain
compilers, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.