diff options
author | Edward Barnard <eabarnard@gmail.com> | 2015-01-03 14:03:44 +0000 |
---|---|---|
committer | Edward Barnard <eabarnard@gmail.com> | 2015-01-03 14:29:53 +0000 |
commit | b016bc541ad172479f83615eddf49c129b2ddb74 (patch) | |
tree | ca78451bac5a12f94d343cdc119fb622a973dcde | |
parent | 76b8db5f9b1ed4637707574950a9c34a2ac3e1fe (diff) |
Recurse through arrays and pointers to anonymous structs. Closes #150.
-rw-r--r-- | src/parser.rs | 31 | ||||
-rw-r--r-- | tests/headers/struct_with_anon_struct_array.h | 4 | ||||
-rw-r--r-- | tests/test_struct.rs | 49 |
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] |