summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/comp.rs19
-rw-r--r--tests/expectations/tests/issue-639-typedef-anon-field.rs81
-rw-r--r--tests/headers/issue-639-typedef-anon-field.hpp15
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;
+};