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

オープン
#3,398 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
52/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
c, cpp, rust
領域
compilers, tooling

調査の方向性

まず、bindgen が示された input.h の宣言を処理するときに、CXType_Unexposed 型がどのように opaque blob fallback に入るのかを追跡します。reproducer 上で bindgen を実行し、破棄された extern 変数も含めて signed と unsigned _BitInt の結果を比較します。既存の unsigned _BitInt(128) のマッピングを変更せずに、符号性と幅が保持されるか、エラーが報告されれば完了です。

索引モデルが issue の本文から書いたものです。

説明

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.

主要言語
Rust
スター
5.3k
フォーク
846
平均マージ
2日 6時間
マージ済み PR(30日)
11

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

rust-lang/rust-bindgen のほかの issue

rust-lang/rust-bindgen の issue をすべて見る

似ている issue

Rust の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。