diff options
-rw-r--r-- | src/parser.rs | 4 | ||||
-rw-r--r-- | src/types.rs | 38 | ||||
-rw-r--r-- | tests/expectations/vtable_recursive_sig.rs | 36 | ||||
-rw-r--r-- | tests/headers/vtable_recursive_sig.hpp | 11 |
4 files changed, 86 insertions, 3 deletions
diff --git a/src/parser.rs b/src/parser.rs index a3311b24..bb1e535d 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -987,8 +987,8 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, } } for base in ci.members[..ci.base_members].iter() { - let base = match base { - &CompMember::Field(ref fi) => { + let base = match *base { + CompMember::Field(ref fi) => { match fi.ty { TComp(ref ci) => ci.clone(), _ => continue, diff --git a/src/types.rs b/src/types.rs index 9f640620..30a4f454 100644 --- a/src/types.rs +++ b/src/types.rs @@ -167,7 +167,8 @@ pub struct FuncSig { pub abi: abi::Abi, } -#[derive(Clone, PartialEq, Debug)] +// NOTE: Remember to add your new variant to the PartialEq implementation below! +#[derive(Clone, Debug)] pub enum Type { TVoid, TInt(IKind, Layout), @@ -181,6 +182,41 @@ pub enum Type { TEnum(Rc<RefCell<EnumInfo>>) } +/// Compares to Rc<T> types looking first at the value they point to. +/// +/// This is needed to avoid infinite recursion in things like virtual function +/// signatures. +fn ref_ptr_aware_eq<T: PartialEq>(one: &Rc<T>, other: &Rc<T>) -> bool { + &**one as *const T == &**other as *const T || + **one == **other +} + +impl PartialEq for Type { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (&TVoid, &TVoid) + => true, + (&TInt(ref kind, ref l), &TInt(ref o_kind, ref o_l)) + => kind == o_kind && l == o_l, + (&TFloat(ref kind, ref l), &TFloat(ref o_kind, ref o_l)) + => kind == o_kind && l == o_l, + (&TPtr(ref ty, is_const, is_ref, ref l), &TPtr(ref o_ty, o_is_const, o_is_ref, ref o_l)) + => is_const == o_is_const && is_ref == o_is_ref && l == o_l && ty == o_ty, + (&TArray(ref ty, count, ref l), &TArray(ref o_ty, o_count, ref o_l)) + => count == o_count && l == o_l && ty == o_ty, + (&TFuncProto(ref sig), &TFuncProto(ref o_sig)) + => sig == o_sig, + (&TNamed(ref ti), &TNamed(ref o_ti)) + => ref_ptr_aware_eq(ti, o_ti), + (&TComp(ref ci), &TComp(ref o_ci)) + => ref_ptr_aware_eq(ci, o_ci), + (&TEnum(ref ei), &TEnum(ref o_ei)) + => ref_ptr_aware_eq(ei, o_ei), + _ => false, + } + } +} + impl Type { #[allow(dead_code)] pub fn name(&self) -> Option<String> { diff --git a/tests/expectations/vtable_recursive_sig.rs b/tests/expectations/vtable_recursive_sig.rs new file mode 100644 index 00000000..8f972e92 --- /dev/null +++ b/tests/expectations/vtable_recursive_sig.rs @@ -0,0 +1,36 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Base { + pub _vftable: *const _vftable_Base, +} +#[repr(C)] +pub struct _vftable_Base { + pub AsDerived: unsafe extern "C" fn(this: *mut ::std::os::raw::c_void) + -> *mut Derived, +} +impl ::std::clone::Clone for Base { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_Base() { + assert_eq!(::std::mem::size_of::<Base>() , 8usize); + assert_eq!(::std::mem::align_of::<Base>() , 8usize); +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Derived { + pub _base: Base, +} +#[repr(C)] +pub struct _vftable_Derived { + pub _base: _vftable_Base, +} +impl ::std::clone::Clone for Derived { + fn clone(&self) -> Self { *self } +} diff --git a/tests/headers/vtable_recursive_sig.hpp b/tests/headers/vtable_recursive_sig.hpp new file mode 100644 index 00000000..4e5af806 --- /dev/null +++ b/tests/headers/vtable_recursive_sig.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: -std=c++11 -no-type-renaming + +class Derived; +class Base { +public: + virtual Derived* AsDerived() { return nullptr; } +}; + +class Derived final : public Base { + virtual Derived* AsDerived() override { return this; } +}; |