Open
Description
Input C/C++ Header
#include <cstdint>
struct Foo {
size_t data;
};
struct Bar {
size_t data;
~Bar() { data = 0; }
};
Foo MakeFoo(); // { return Foo(); }
Bar MakeBar(); // { return Bar(); }
Bindgen Invocation
bindgen::Builder::default()
.clang_args(&["-x","c++", "-std=c++11"])
.header("input.h")
.generate()
.unwrap()
Actual Results
#[repr(C)]
#[derive(Debug, Copy)]
pub struct Foo {
pub data: usize,
}
impl Clone for Foo {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
#[derive(Debug)]
pub struct Bar {
pub data: usize,
}
extern "C" {
#[link_name = "_ZN3BarD1Ev"]
pub fn Bar_Bar_destructor(this: *mut Bar);
}
impl Bar {
#[inline]
pub unsafe fn destruct(&mut self) { Bar_Bar_destructor(self) }
}
extern "C" {
#[link_name = "_Z7MakeFoov"]
pub fn MakeFoo() -> Foo;
}
extern "C" {
#[link_name = "_Z7MakeBarv"]
pub fn MakeBar() -> Bar;
}
Expected Results
Not sure...
Discussion
MakeFoo
and MakeBar
look very similar, however in C++ they use different ABIs, at least on Linux.
Here's a quote from System V AMD64 ABI spec (page 20):
If a C++ object has either a non-trivial copy constructor or a non-trivial
destructor 11, it is passed by invisible reference (the object is replaced in the
parameter list by a pointer that has class POINTER) 12
This means that while Foo
get returned by-value in the rax
register, Bar
must be returned by-pointer to a caller allocated memory. To Rust compiler, however, these look identical, so it expects both to be returned in rax
.