rust-lang / rust-lang/rust-bindgen
C++ empty class by-value arguments are passed even though clang omits them
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
struct E {};
int take(E e, int x);
int take(E e, int x) { (void)e; return x + 1; }
Bindgen Invocation
$ bindgen input.h --enable-cxx-namespaces --output bindings.rs -- -x c++ -std=c++20
Layout tests are left on (the default).
Actual Results
sizeof(E) is 1 in both clang++ and the generated Rust, so the layout tests compile.
clang++ does not pass the empty class at all:
define i32 @_Z4take1Ei(i32 noundef %0)
; caller:
call i32 @_Z4take1Ei(i32 noundef 10)
bindgen still emits a 1-byte argument:
pub struct E { pub _address: u8 }
pub fn take(e: root::E, x: c_int) -> c_int;
rustc therefore calls with two arguments:
declare i32 @"\01__Z4take1Ei"(i64, i32)
call i32 @"\01__Z4take1Ei"(i64 %1, i32 10)
Runtime, take(E{}, 10):
C++: 11
Rust: 1
bindgen does not panic. rustc accepts the bindings, including the layout tests.
Expected Results
The generated signature should match the C++ ABI used by clang: the empty class parameter is not passed, so take is effectively fn(c_int) -> c_int (or whatever equivalent rustc will lower the same way). Passing a dummy E by value makes rustc pass an extra integer and shifts the real arguments.
Environment
bindgen: 0.72.1
clang++: Apple clang 21.0.0
rustc: 1.97.1
target: aarch64-apple-darwin
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the bindgen invocation with input.h and inspect the generated bindings.rs, then compare the emitted LLVM calls with clang++ for the empty C++ class argument. Done means the generated signature follows the clang ABI without passing a dummy E value and the runtime call returns 11.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100