summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Barnard <eabarnard@gmail.com>2015-01-03 14:03:44 +0000
committerEdward Barnard <eabarnard@gmail.com>2015-01-03 14:29:53 +0000
commitb016bc541ad172479f83615eddf49c129b2ddb74 (patch)
treeca78451bac5a12f94d343cdc119fb622a973dcde
parent76b8db5f9b1ed4637707574950a9c34a2ac3e1fe (diff)
Recurse through arrays and pointers to anonymous structs. Closes #150.
-rw-r--r--src/parser.rs31
-rw-r--r--tests/headers/struct_with_anon_struct_array.h4
-rw-r--r--tests/test_struct.rs49
3 files changed, 63 insertions, 21 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 0e05537a..5740f52b 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -358,9 +358,8 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
// The Clang C api does not fully expose composite fields, but it
// does expose them in a way that can be detected. When the current
- // field kind is CXType_Unexposed, CXType_Pointer or
- // CXType_ConstantArray and the previous member is a
- // composite type--the same type as this field-- then this is a
+ // field kind is TComp, TPtr or TArray and the previous member is a
+ // composite type - the same type as this field - then this is a
// composite field. e.g.:
//
// struct foo {
@@ -374,25 +373,31 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
// union {
// int a;
// char b;
- // } *bar;
+ // } **bar;
// };
//
// struct foo {
// union {
// int a;
// char b;
- // } bar[3];
+ // } bar[3][2];
// };
//
- let is_composite = match (cursor.cur_type().kind(), &ty) {
- (CXType_Unexposed, &TComp(ref ty_compinfo)) |
- (CXType_Pointer, &TPtr(box TComp(ref ty_compinfo), _, _)) |
- (CXType_ConstantArray, &TArray(box TComp(ref ty_compinfo), _, _)) => {
- if let Some(&CompMember::Comp(ref c)) = members.last() {
- c.borrow().deref() as *const _ == ty_compinfo.borrow().deref() as *const _
- } else {
- false
+
+ fn inner_composite(mut ty: &il::Type) -> Option<&Rc<RefCell<CompInfo>>> {
+ loop {
+ match ty {
+ &TComp(ref comp_ty) => return Some(comp_ty),
+ &TPtr(ref ptr_ty, _, _) => ty = &**ptr_ty,
+ &TArray(ref array_ty, _, _) => ty = &**array_ty,
+ _ => return None
}
+ }
+ }
+
+ let is_composite = match (inner_composite(&ty), members.last()) {
+ (Some(ty_compinfo), Some(&CompMember::Comp(ref c))) => {
+ c.borrow().deref() as *const _ == ty_compinfo.borrow().deref() as *const _
},
_ => false
};
diff --git a/tests/headers/struct_with_anon_struct_array.h b/tests/headers/struct_with_anon_struct_array.h
index 2d9d7bdd..9ea977e8 100644
--- a/tests/headers/struct_with_anon_struct_array.h
+++ b/tests/headers/struct_with_anon_struct_array.h
@@ -3,4 +3,8 @@ struct foo {
int a;
int b;
} bar[2];
+ struct {
+ int a;
+ int b;
+ } baz[2][3][4];
};
diff --git a/tests/test_struct.rs b/tests/test_struct.rs
index d9d8f930..3a9e3550 100644
--- a/tests/test_struct.rs
+++ b/tests/test_struct.rs
@@ -14,14 +14,47 @@ fn with_anon_struct() {
#[test]
fn with_anon_struct_array() {
- mod ffi { bindgen!("headers/struct_with_anon_struct_array.h"); }
- let mut x: ffi::Struct_foo = Default::default();
-
- x.bar[1].a = 1;
- x.bar[1].b = 2;
-
- assert_eq!(x.bar[1].a, 1);
- assert_eq!(x.bar[1].b, 2);
+ assert_bind_eq!("headers/struct_with_anon_struct_array.h", cx,
+ quote_item!(cx,
+ #[repr(C)]
+ #[deriving(Copy)]
+ pub struct Struct_foo {
+ pub bar: [Struct_Unnamed1; 2u],
+ pub baz: [[[Struct_Unnamed2; 4u]; 3u]; 2u],
+ }
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_foo {
+ fn default() -> Struct_foo { unsafe { ::std::mem::zeroed() } }
+ }
+ ),
+ quote_item!(cx,
+ #[repr(C)]
+ #[deriving(Copy)]
+ pub struct Struct_Unnamed1 {
+ pub a: ::libc::c_int,
+ pub b: ::libc::c_int,
+ }
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_Unnamed1 {
+ fn default() -> Struct_Unnamed1 { unsafe { ::std::mem::zeroed() } }
+ }
+ ),
+ quote_item!(cx,
+ #[repr(C)]
+ #[deriving(Copy)]
+ pub struct Struct_Unnamed2 {
+ pub a: ::libc::c_int,
+ pub b: ::libc::c_int,
+ }
+ ),
+ quote_item!(cx,
+ impl ::std::default::Default for Struct_Unnamed2 {
+ fn default() -> Struct_Unnamed2 { unsafe { ::std::mem::zeroed() } }
+ }
+ )
+ );
}
#[test]