rust-lang / rust-lang/rust-bindgen
Bindgen Incorrectly Mangles C++ Struct/Class Destructor with MSVC ABI
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
This is done on Windows 10. Linux appears to work as expected.
bindgen: 0.53.1
LLVM: 9.0.0 from installer
Correct mangling shown on godbolt. clang-cl isn't shown, but outputs the same, as is expected.
Input C/C++ Header
struct B{
B();
~B();
};
// Bindgen incorrectly demangles this as ??_DB@@QEAAXXZ
// real: ??1B@@QEAA@XZ
B::~B() {}
class C{
public:
C();
~C();
};
// Bindgen incorrectly demangles this as ??_DC@@QEAAXXZ (same as struct)
// symbol: ??1C@@AEAA@XZ (note the A in AEAA)
C::~C() {}
Bindgen Invocation
$ bindgen file.hpp
Actual Results
Verbose Output
These look pretty important 😛
cargo:warning=couldn't execute `llvm-config --prefix` (error: The system cannot find the file specified. (os error 2))
cargo:warning=set the LLVM_CONFIG_PATH environment variable to a valid `llvm-config` executable
[2020-02-11T06:08:18Z ERROR bindgen::ir::item] Unhandled cursor kind 25: Cursor(~B kind: CXXDestructor, loc: .\file.hpp:8:4, usr: Some("c:@S@B@F@~B#"))
[2020-02-11T06:08:18Z ERROR bindgen::ir::item] Unhandled cursor kind 25: Cursor(~C kind: CXXDestructor, loc: .\file.hpp:18:4, usr: Some("c:@S@C@F@~C#"))
Bindgen Output
Comments my own.
/* automatically generated by rust-bindgen */
#[repr(C)]
#[derive(Debug)]
pub struct B {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_B() {
assert_eq!(
::std::mem::size_of::<B>(),
1usize,
concat!("Size of: ", stringify!(B))
);
assert_eq!(
::std::mem::align_of::<B>(),
1usize,
concat!("Alignment of ", stringify!(B))
);
}
extern "C" {
#[link_name = "\u{1}??0B@@QEAA@XZ"]
pub fn B_B(this: *mut B);
}
extern "C" {
// incorrect, should be: ??1B@@QEAA@XZ
#[link_name = "\u{1}??_DB@@QEAAXXZ"]
pub fn B_B_destructor(this: *mut B);
}
impl B {
#[inline]
pub unsafe fn new() -> Self {
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
B_B(__bindgen_tmp.as_mut_ptr());
__bindgen_tmp.assume_init()
}
#[inline]
pub unsafe fn destruct(&mut self) {
B_B_destructor(self)
}
}
#[repr(C)]
#[derive(Debug)]
pub struct C {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_C() {
assert_eq!(
::std::mem::size_of::<C>(),
1usize,
concat!("Size of: ", stringify!(C))
);
assert_eq!(
::std::mem::align_of::<C>(),
1usize,
concat!("Alignment of ", stringify!(C))
);
}
extern "C" {
#[link_name = "\u{1}??0C@@QEAA@XZ"]
pub fn C_C(this: *mut C);
}
extern "C" {
// incorrect, should be ??1C@@AEAA@XZ
#[link_name = "\u{1}??_DC@@QEAAXXZ"]
pub fn C_C_destructor(this: *mut C);
}
impl C {
#[inline]
pub unsafe fn new() -> Self {
let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit();
C_C(__bindgen_tmp.as_mut_ptr());
__bindgen_tmp.assume_init()
}
#[inline]
pub unsafe fn destruct(&mut self) {
C_C_destructor(self)
}
}
Expected Results
As mentioned above, the destructors are getting mangled incorrectly on the MSVC abi. Specifically:
??1C@@AEAA@XZ gets mangled as ??_DC@@QEAAXXZ and
??1B@@QEAA@XZ gets mangled as ??_DB@@QEAAXXZ.
This gives a linker error that is quite confusing talking about a missing reference to a vbase destructor on a class with no parents nor virtuality.
Workaround
For those affected by the issue, if you post process the bindings with a regex, you can automatically filter these:
\?\?_D(.*?)XXZ -> ??1${1}@XZ
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
Reproduce the issue on Windows using file.hpp, bindgen 0.53.1, and LLVM 9.0.0, then trace how the reported CXXDestructor cursors are handled. Compare the generated MSVC symbols with the expected destructor names shown in the issue. Done means destructors for both the struct and class produce the expected link names and the behavior is covered by a regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, rust
- Domain
- compilers, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100