rust-lang / rust-bindgen

Automatically generates Rust FFI bindings to C (and some C++) libraries.
https://rust-lang.github.io/rust-bindgen/
BSD 3-Clause "New" or "Revised" License
4.43k stars 695 forks source link

bindgen hangs on c++ header #1918

Open boydjohnson opened 3 years ago

boydjohnson commented 3 years ago

c++ header

template <typename> struct a;
template <typename, typename, typename, typename, typename, typename, typename, typename, typename, bool> struct b;
template <typename d, typename c, typename f, typename e, typename h, typename g, typename j, typename i, typename l>
struct b<d, c, f, e, h, g, j, i, l, true> {
  using k = a<l>;
  using n = typename k::n;
  using m = typename c ::o;
  m &p(const n &);
};
template <typename d, typename c, typename f, typename e, typename h, typename g, typename j, typename i, typename l>
auto b<d, c, f, e, h, g, j, i, l, true>::p(const n &) -> m & {}

bindgen test-case-5.hpp -- -x c++ hangs.

This hangs bindgen for at least several minutes. The interestingness test I used with creduce was that it would hang it for 2m:30s.

Using RUST_LOG=bindgen on the executable shows that it gets into the codegen phase.

boydjohnson commented 3 years ago

These are the warnings from RUST_LOG=bindgen=warn:

[2020-11-10T15:55:06Z WARN  bindgen::ir::comp] Unknown kind for comp type: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)
[2020-11-10T15:55:06Z WARN  bindgen::ir::comp] Unknown kind for comp type: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)
[2020-11-10T15:55:06Z WARN  bindgen::ir::ty] Found a partial template specialization; bindgen does not support partial template specialization! Constructing opaque type instead.
[2020-11-10T15:55:06Z WARN  bindgen::ir::item] Unhandled cursor kind 21: Cursor(p kind: CXXMethod, loc: test-case-5.hpp:15:42, usr: Some("c:@SP>9#T#T#T#T#T#T#T#T#T@b>#t0.0#t0.1#t0.2#t0.3#t0.4#t0.5#t0.6#t0.7#t0.8#Vb1@F@p#&1^a<type-parameter-0-8>:::n#"))
[2020-11-10T15:55:06Z WARN  bindgen::ir::ty] Unexposed type Type(typename k::n, kind: Unexposed, cconv: 100, decl: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None), canon: Cursor( kind: NoDeclFound, loc: builtin definitions, usr: None)), recursing inside, loc: Cursor( kind: ParmDecl, loc: test-case-5.hpp:15:53, usr: None)
emilio commented 3 years ago

Huh, cool one :)

It seems this is one of the cases where we create a cyclic AST, and we get stuck traversing it.

boydjohnson commented 3 years ago

@emilio Thanks for your time on these. I hope what I have provided is helpful. I know that work on this tool is above me at the moment, so I am just thankful.

boydjohnson commented 3 years ago

@emilio On master now, this header produces:

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct a {
    pub _address: u8,
}

It no longer hangs but doesn't generate bindings for b, probably due to the templating complexity.