diff options
-rw-r--r-- | src/ir/comp.rs | 19 | ||||
-rw-r--r-- | tests/expectations/tests/issue-639-typedef-anon-field.rs | 81 | ||||
-rw-r--r-- | tests/headers/issue-639-typedef-anon-field.hpp | 15 |
3 files changed, 110 insertions, 5 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 80c51b8f..7a85794b 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -500,11 +500,19 @@ impl CompInfo { let mut maybe_anonymous_struct_field = None; cursor.visit(|cur| { if cur.kind() != CXCursor_FieldDecl { - if let Some((ty, _, offset)) = + if let Some((ty, clang_ty, offset)) = maybe_anonymous_struct_field.take() { - let field = - Field::new(None, ty, None, None, None, false, offset); - ci.fields.push(field); + if cur.kind() == CXCursor_TypedefDecl && + cur.typedef_type().unwrap().canonical_type() == clang_ty { + // Typedefs of anonymous structs appear later in the ast + // than the struct itself, that would otherwise be an + // anonymous field. Detect that case here, and do + // nothing. + } else { + let field = + Field::new(None, ty, None, None, None, false, offset); + ci.fields.push(field); + } } } @@ -737,7 +745,8 @@ impl CompInfo { }); if let Some((ty, _, offset)) = maybe_anonymous_struct_field { - let field = Field::new(None, ty, None, None, None, false, offset); + let field = + Field::new(None, ty, None, None, None, false, offset); ci.fields.push(field); } diff --git a/tests/expectations/tests/issue-639-typedef-anon-field.rs b/tests/expectations/tests/issue-639-typedef-anon-field.rs new file mode 100644 index 00000000..8d5709f4 --- /dev/null +++ b/tests/expectations/tests/issue-639-typedef-anon-field.rs @@ -0,0 +1,81 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Foo { + pub bar: Foo_Bar, +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Foo_Bar { + pub abc: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_Foo_Bar() { + assert_eq!(::std::mem::size_of::<Foo_Bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Foo_Bar ) )); + assert_eq! (::std::mem::align_of::<Foo_Bar>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Foo_Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Foo_Bar ) ) . abc as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Foo_Bar ) , "::" , + stringify ! ( abc ) )); +} +impl Clone for Foo_Bar { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_Foo() { + assert_eq!(::std::mem::size_of::<Foo>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Foo ) )); + assert_eq! (::std::mem::align_of::<Foo>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Foo ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Foo ) ) . bar as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Foo ) , "::" , + stringify ! ( bar ) )); +} +impl Clone for Foo { + fn clone(&self) -> Self { *self } +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Baz { + pub _address: u8, +} +#[repr(C)] +#[derive(Debug, Default, Copy)] +pub struct Baz_Bar { + pub abc: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_Baz_Bar() { + assert_eq!(::std::mem::size_of::<Baz_Bar>() , 4usize , concat ! ( + "Size of: " , stringify ! ( Baz_Bar ) )); + assert_eq! (::std::mem::align_of::<Baz_Bar>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( Baz_Bar ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const Baz_Bar ) ) . abc as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( Baz_Bar ) , "::" , + stringify ! ( abc ) )); +} +impl Clone for Baz_Bar { + fn clone(&self) -> Self { *self } +} +#[test] +fn bindgen_test_layout_Baz() { + assert_eq!(::std::mem::size_of::<Baz>() , 1usize , concat ! ( + "Size of: " , stringify ! ( Baz ) )); + assert_eq! (::std::mem::align_of::<Baz>() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Baz ) )); +} +impl Clone for Baz { + fn clone(&self) -> Self { *self } +} diff --git a/tests/headers/issue-639-typedef-anon-field.hpp b/tests/headers/issue-639-typedef-anon-field.hpp new file mode 100644 index 00000000..efd6c4f4 --- /dev/null +++ b/tests/headers/issue-639-typedef-anon-field.hpp @@ -0,0 +1,15 @@ +class Foo { + public: + typedef struct { + int abc; + } Bar; + + Bar bar; +}; + +class Baz { + public: + typedef struct { + int abc; + } Bar; +}; |