summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-02-07 13:35:34 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-02-10 14:03:04 +0100
commit7e1b7d98d1da5a449ae18f6f60bac29b9079b9ab (patch)
treec210115eb181cbf45adc553f8aaaec557644db65
parent0ae42f2c55305aab12b2f55346001b7d5539cb6f (diff)
ir: Don't parse non-semantic-children cursor as inner structs.
Fixes: https://github.com/servo/rust-bindgen/issues/482
-rw-r--r--src/codegen/mod.rs2
-rw-r--r--src/ir/comp.rs15
-rw-r--r--tests/expectations/tests/class_nested.rs43
-rw-r--r--tests/expectations/tests/layout_array.rs3
-rw-r--r--tests/expectations/tests/layout_cmdline_token.rs107
-rw-r--r--tests/expectations/tests/layout_mbuf.rs3
-rw-r--r--tests/expectations/tests/struct_containing_forward_declared_struct.rs42
-rw-r--r--tests/headers/class_nested.hpp12
8 files changed, 138 insertions, 89 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 7469abb9..99400f7a 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2190,7 +2190,7 @@ impl ToRustTy for Type {
.map(|arg| arg.to_rust_ty(ctx))
.collect::<Vec<_>>();
- path.segments.last_mut().unwrap().parameters = if
+ path.segments.last_mut().unwrap().parameters = if
template_args.is_empty() {
None
} else {
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index b02cd342..7c58e233 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -669,11 +669,20 @@ impl CompInfo {
CXCursor_UnionDecl |
CXCursor_ClassTemplate |
CXCursor_ClassDecl => {
+ // We can find non-semantic children here, clang uses a
+ // StructDecl to note incomplete structs that hasn't been
+ // forward-declared before, see:
+ //
+ // https://github.com/servo/rust-bindgen/issues/482
+ if cur.semantic_parent() != cursor {
+ return CXChildVisit_Continue;
+ }
+
let inner = Item::parse(cur, Some(potential_id), ctx)
.expect("Inner ClassDecl");
- if !ci.inner_types.contains(&inner) {
- ci.inner_types.push(inner);
- }
+
+ ci.inner_types.push(inner);
+
// A declaration of an union or a struct without name could
// also be an unnamed field, unfortunately.
if cur.spelling().is_empty() &&
diff --git a/tests/expectations/tests/class_nested.rs b/tests/expectations/tests/class_nested.rs
index 19d70e50..6ddcf91b 100644
--- a/tests/expectations/tests/class_nested.rs
+++ b/tests/expectations/tests/class_nested.rs
@@ -29,6 +29,34 @@ fn bindgen_test_layout_A_B() {
impl Clone for A_B {
fn clone(&self) -> Self { *self }
}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct A_C {
+ pub baz: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_A_C() {
+ assert_eq!(::std::mem::size_of::<A_C>() , 4usize , concat ! (
+ "Size of: " , stringify ! ( A_C ) ));
+ assert_eq! (::std::mem::align_of::<A_C>() , 4usize , concat ! (
+ "Alignment of " , stringify ! ( A_C ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const A_C ) ) . baz as * const _ as usize } ,
+ 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( A_C ) , "::" ,
+ stringify ! ( baz ) ));
+}
+impl Clone for A_C {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct A_D<T> {
+ pub foo: T,
+}
+impl <T> Default for A_D<T> {
+ fn default() -> Self { unsafe { ::std::mem::zeroed() } }
+}
#[test]
fn bindgen_test_layout_A() {
assert_eq!(::std::mem::size_of::<A>() , 4usize , concat ! (
@@ -48,6 +76,21 @@ extern "C" {
#[link_name = "var"]
pub static mut var: A_B;
}
+#[test]
+fn __bindgen_test_layout_template_1() {
+ assert_eq!(::std::mem::size_of::<A_D<::std::os::raw::c_int>>() , 4usize ,
+ concat ! (
+ "Size of template specialization: " , stringify ! (
+ A_D<::std::os::raw::c_int> ) ));
+ assert_eq!(::std::mem::align_of::<A_D<::std::os::raw::c_int>>() , 4usize ,
+ concat ! (
+ "Alignment of template specialization: " , stringify ! (
+ A_D<::std::os::raw::c_int> ) ));
+}
+extern "C" {
+ #[link_name = "baz"]
+ pub static mut baz: A_D<::std::os::raw::c_int>;
+}
#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct D {
diff --git a/tests/expectations/tests/layout_array.rs b/tests/expectations/tests/layout_array.rs
index 3f86cda9..facf9462 100644
--- a/tests/expectations/tests/layout_array.rs
+++ b/tests/expectations/tests/layout_array.rs
@@ -202,9 +202,6 @@ pub struct malloc_heap {
pub struct malloc_heap__bindgen_ty_1 {
pub lh_first: *mut malloc_heap__bindgen_ty_1_malloc_elem,
}
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct malloc_heap__bindgen_ty_1_malloc_elem([u8; 0]);
#[test]
fn bindgen_test_layout_malloc_heap__bindgen_ty_1() {
assert_eq!(::std::mem::size_of::<malloc_heap__bindgen_ty_1>() , 8usize ,
diff --git a/tests/expectations/tests/layout_cmdline_token.rs b/tests/expectations/tests/layout_cmdline_token.rs
index 35127399..791ea9b3 100644
--- a/tests/expectations/tests/layout_cmdline_token.rs
+++ b/tests/expectations/tests/layout_cmdline_token.rs
@@ -11,9 +11,33 @@
#[repr(C)]
#[derive(Debug, Copy)]
pub struct cmdline_token_hdr {
- pub ops: *mut cmdline_token_hdr_cmdline_token_ops,
+ pub ops: *mut cmdline_token_ops,
pub offset: ::std::os::raw::c_uint,
}
+#[test]
+fn bindgen_test_layout_cmdline_token_hdr() {
+ assert_eq!(::std::mem::size_of::<cmdline_token_hdr>() , 16usize , concat !
+ ( "Size of: " , stringify ! ( cmdline_token_hdr ) ));
+ assert_eq! (::std::mem::align_of::<cmdline_token_hdr>() , 8usize , concat
+ ! ( "Alignment of " , stringify ! ( cmdline_token_hdr ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const cmdline_token_hdr ) ) . ops as * const _
+ as usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_hdr ) ,
+ "::" , stringify ! ( ops ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const cmdline_token_hdr ) ) . offset as * const
+ _ as usize } , 8usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_hdr ) ,
+ "::" , stringify ! ( offset ) ));
+}
+impl Clone for cmdline_token_hdr {
+ fn clone(&self) -> Self { *self }
+}
+impl Default for cmdline_token_hdr {
+ fn default() -> Self { unsafe { ::std::mem::zeroed() } }
+}
+pub type cmdline_parse_token_hdr_t = cmdline_token_hdr;
/**
* A token is defined by this structure.
*
@@ -35,7 +59,7 @@ pub struct cmdline_token_hdr {
*/
#[repr(C)]
#[derive(Debug, Copy)]
-pub struct cmdline_token_hdr_cmdline_token_ops {
+pub struct cmdline_token_ops {
/** parse(token ptr, buf, res pts, buf len) */
pub parse: ::std::option::Option<unsafe extern "C" fn(arg1:
*mut cmdline_parse_token_hdr_t,
@@ -70,71 +94,38 @@ pub struct cmdline_token_hdr_cmdline_token_ops {
-> ::std::os::raw::c_int>,
}
#[test]
-fn bindgen_test_layout_cmdline_token_hdr_cmdline_token_ops() {
- assert_eq!(::std::mem::size_of::<cmdline_token_hdr_cmdline_token_ops>() ,
- 32usize , concat ! (
- "Size of: " , stringify ! ( cmdline_token_hdr_cmdline_token_ops
- ) ));
- assert_eq! (::std::mem::align_of::<cmdline_token_hdr_cmdline_token_ops>()
- , 8usize , concat ! (
- "Alignment of " , stringify ! (
- cmdline_token_hdr_cmdline_token_ops ) ));
+fn bindgen_test_layout_cmdline_token_ops() {
+ assert_eq!(::std::mem::size_of::<cmdline_token_ops>() , 32usize , concat !
+ ( "Size of: " , stringify ! ( cmdline_token_ops ) ));
+ assert_eq! (::std::mem::align_of::<cmdline_token_ops>() , 8usize , concat
+ ! ( "Alignment of " , stringify ! ( cmdline_token_ops ) ));
assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr_cmdline_token_ops ) ) .
- parse as * const _ as usize } , 0usize , concat ! (
- "Alignment of field: " , stringify ! (
- cmdline_token_hdr_cmdline_token_ops ) , "::" , stringify ! (
- parse ) ));
+ & ( * ( 0 as * const cmdline_token_ops ) ) . parse as * const
+ _ as usize } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_ops ) ,
+ "::" , stringify ! ( parse ) ));
assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr_cmdline_token_ops ) ) .
- complete_get_nb as * const _ as usize } , 8usize , concat ! (
- "Alignment of field: " , stringify ! (
- cmdline_token_hdr_cmdline_token_ops ) , "::" , stringify ! (
- complete_get_nb ) ));
+ & ( * ( 0 as * const cmdline_token_ops ) ) . complete_get_nb
+ as * const _ as usize } , 8usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_ops ) ,
+ "::" , stringify ! ( complete_get_nb ) ));
assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr_cmdline_token_ops ) ) .
- complete_get_elt as * const _ as usize } , 16usize , concat !
- (
- "Alignment of field: " , stringify ! (
- cmdline_token_hdr_cmdline_token_ops ) , "::" , stringify ! (
- complete_get_elt ) ));
+ & ( * ( 0 as * const cmdline_token_ops ) ) . complete_get_elt
+ as * const _ as usize } , 16usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_ops ) ,
+ "::" , stringify ! ( complete_get_elt ) ));
assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr_cmdline_token_ops ) ) .
- get_help as * const _ as usize } , 24usize , concat ! (
- "Alignment of field: " , stringify ! (
- cmdline_token_hdr_cmdline_token_ops ) , "::" , stringify ! (
- get_help ) ));
+ & ( * ( 0 as * const cmdline_token_ops ) ) . get_help as *
+ const _ as usize } , 24usize , concat ! (
+ "Alignment of field: " , stringify ! ( cmdline_token_ops ) ,
+ "::" , stringify ! ( get_help ) ));
}
-impl Clone for cmdline_token_hdr_cmdline_token_ops {
+impl Clone for cmdline_token_ops {
fn clone(&self) -> Self { *self }
}
-impl Default for cmdline_token_hdr_cmdline_token_ops {
+impl Default for cmdline_token_ops {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
-#[test]
-fn bindgen_test_layout_cmdline_token_hdr() {
- assert_eq!(::std::mem::size_of::<cmdline_token_hdr>() , 16usize , concat !
- ( "Size of: " , stringify ! ( cmdline_token_hdr ) ));
- assert_eq! (::std::mem::align_of::<cmdline_token_hdr>() , 8usize , concat
- ! ( "Alignment of " , stringify ! ( cmdline_token_hdr ) ));
- assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr ) ) . ops as * const _
- as usize } , 0usize , concat ! (
- "Alignment of field: " , stringify ! ( cmdline_token_hdr ) ,
- "::" , stringify ! ( ops ) ));
- assert_eq! (unsafe {
- & ( * ( 0 as * const cmdline_token_hdr ) ) . offset as * const
- _ as usize } , 8usize , concat ! (
- "Alignment of field: " , stringify ! ( cmdline_token_hdr ) ,
- "::" , stringify ! ( offset ) ));
-}
-impl Clone for cmdline_token_hdr {
- fn clone(&self) -> Self { *self }
-}
-impl Default for cmdline_token_hdr {
- fn default() -> Self { unsafe { ::std::mem::zeroed() } }
-}
-pub type cmdline_parse_token_hdr_t = cmdline_token_hdr;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum cmdline_numtype {
diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs
index c0c2cce2..7bd3bf1a 100644
--- a/tests/expectations/tests/layout_mbuf.rs
+++ b/tests/expectations/tests/layout_mbuf.rs
@@ -490,9 +490,6 @@ impl Clone for rte_mbuf__bindgen_ty_4 {
fn clone(&self) -> Self { *self }
}
#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct rte_mbuf_rte_mempool([u8; 0]);
-#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct rte_mbuf__bindgen_ty_5 {
/**< combined for easy fetch */
diff --git a/tests/expectations/tests/struct_containing_forward_declared_struct.rs b/tests/expectations/tests/struct_containing_forward_declared_struct.rs
index ff16490a..58ab04c9 100644
--- a/tests/expectations/tests/struct_containing_forward_declared_struct.rs
+++ b/tests/expectations/tests/struct_containing_forward_declared_struct.rs
@@ -7,27 +7,7 @@
#[repr(C)]
#[derive(Debug, Copy)]
pub struct a {
- pub val_a: *mut a_b,
-}
-#[repr(C)]
-#[derive(Debug, Default, Copy)]
-pub struct a_b {
- pub val_b: ::std::os::raw::c_int,
-}
-#[test]
-fn bindgen_test_layout_a_b() {
- assert_eq!(::std::mem::size_of::<a_b>() , 4usize , concat ! (
- "Size of: " , stringify ! ( a_b ) ));
- assert_eq! (::std::mem::align_of::<a_b>() , 4usize , concat ! (
- "Alignment of " , stringify ! ( a_b ) ));
- assert_eq! (unsafe {
- & ( * ( 0 as * const a_b ) ) . val_b as * const _ as usize } ,
- 0usize , concat ! (
- "Alignment of field: " , stringify ! ( a_b ) , "::" ,
- stringify ! ( val_b ) ));
-}
-impl Clone for a_b {
- fn clone(&self) -> Self { *self }
+ pub val_a: *mut b,
}
#[test]
fn bindgen_test_layout_a() {
@@ -47,3 +27,23 @@ impl Clone for a {
impl Default for a {
fn default() -> Self { unsafe { ::std::mem::zeroed() } }
}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct b {
+ pub val_b: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_b() {
+ assert_eq!(::std::mem::size_of::<b>() , 4usize , concat ! (
+ "Size of: " , stringify ! ( b ) ));
+ assert_eq! (::std::mem::align_of::<b>() , 4usize , concat ! (
+ "Alignment of " , stringify ! ( b ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const b ) ) . val_b as * const _ as usize } ,
+ 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( b ) , "::" , stringify
+ ! ( val_b ) ));
+}
+impl Clone for b {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/headers/class_nested.hpp b/tests/headers/class_nested.hpp
index ab38d500..ccf2f895 100644
--- a/tests/headers/class_nested.hpp
+++ b/tests/headers/class_nested.hpp
@@ -4,9 +4,21 @@ public:
class B {
int member_b;
};
+
+ class C;
+
+ template<typename T>
+ class D {
+ T foo;
+ };
+};
+
+class A::C {
+ int baz;
};
A::B var;
+A::D<int> baz;
class D {
A::B member;