C++ empty class by-value arguments are passed even though clang omits them

Open
#3,439 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
cpp, rust
Domain
tooling

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.

Description

help wanted
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
Dominant language
Rust
Stars
5.3k
Forks
846
Avg merge
2d 6h
Merged PRs (30d)
11

Getting set up

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.

More from rust-lang/rust-bindgen

All issues in rust-lang/rust-bindgen

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.