diff --git a/src/ir/context.rs b/src/ir/context.rs index 788c3f98b4..3bb8b5d913 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -137,6 +137,14 @@ pub struct BindgenContext<'ctx> { /// Current module being traversed. current_module: ItemId, + /// A HashMap keyed on a type definition, and whose value is the parent id + /// of the declaration. + /// + /// This is used to handle the cases where the semantic and the lexical + /// parents of the cursor differ, like when a nested class is defined + /// outside of the parent class. + semantic_parents: HashMap, + /// A stack with the current type declarations and types we're parsing. This /// is needed to avoid infinite recursion when parsing a type like: /// @@ -375,6 +383,7 @@ impl<'ctx> BindgenContext<'ctx> { next_item_id: ItemId(1), root_module: root_module.id(), current_module: root_module.id(), + semantic_parents: Default::default(), currently_parsed_types: vec![], parsed_macros: Default::default(), replacements: Default::default(), @@ -1187,6 +1196,31 @@ impl<'ctx> BindgenContext<'ctx> { self.current_module } + /// Add a semantic parent for a given type definition. + /// + /// We do this from the type declaration, in order to be able to find the + /// correct type definition afterwards. + /// + /// TODO(emilio): We could consider doing this only when + /// declaration.lexical_parent() != definition.lexical_parent(), but it's + /// not sure it's worth it. + pub fn add_semantic_parent( + &mut self, + definition: clang::Cursor, + parent_id: ItemId, + ) { + self.semantic_parents.insert(definition, parent_id); + } + + /// Returns a known semantic parent for a given definition. + pub fn known_semantic_parent( + &self, + definition: clang::Cursor + ) -> Option { + self.semantic_parents.get(&definition).cloned() + } + + /// Given a cursor pointing to the location of a template instantiation, /// return a tuple of the form `(declaration_cursor, declaration_id, /// num_expected_template_args)`. diff --git a/src/ir/item.rs b/src/ir/item.rs index b6fe6d4392..0dac1287ed 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1194,11 +1194,31 @@ impl ClangItemParser for Item { // Types are sort of special, so to avoid parsing template classes // twice, handle them separately. { - let applicable_cursor = cursor.definition().unwrap_or(cursor); + let definition = cursor.definition(); + let applicable_cursor = definition.unwrap_or(cursor); + + + let relevant_parent_id = match definition { + Some(definition) => { + if definition != cursor { + ctx.add_semantic_parent(definition, relevant_parent_id); + return Ok(Item::from_ty_or_ref( + applicable_cursor.cur_type(), + cursor, + parent_id, + ctx, + )); + } + parent_id.or_else(|| ctx.known_semantic_parent(definition)) + .unwrap_or(ctx.current_module()) + } + None => relevant_parent_id, + }; + match Item::from_ty( &applicable_cursor.cur_type(), applicable_cursor, - parent_id, + Some(relevant_parent_id), ctx, ) { Ok(ty) => return Ok(ty), diff --git a/tests/expectations/tests/class_nested.rs b/tests/expectations/tests/class_nested.rs index 76658b2e24..a874d6b8f0 100644 --- a/tests/expectations/tests/class_nested.rs +++ b/tests/expectations/tests/class_nested.rs @@ -30,26 +30,6 @@ impl Clone for A_B { fn clone(&self) -> Self { *self } } #[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct A_C { - pub baz: ::std::os::raw::c_int, -} -#[test] -fn bindgen_test_layout_A_C() { - assert_eq!(::std::mem::size_of::() , 4usize , concat ! ( - "Size of: " , stringify ! ( A_C ) )); - assert_eq! (::std::mem::align_of::() , 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, Hash, PartialEq, Eq)] pub struct A_D { pub foo: T, @@ -73,6 +53,26 @@ fn bindgen_test_layout_A() { impl Clone for A { fn clone(&self) -> Self { *self } } +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] +pub struct A_C { + pub baz: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_A_C() { + assert_eq!(::std::mem::size_of::() , 4usize , concat ! ( + "Size of: " , stringify ! ( A_C ) )); + assert_eq! (::std::mem::align_of::() , 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 } +} extern "C" { #[link_name = "var"] pub static mut var: A_B; diff --git a/tests/expectations/tests/forward-inherit-struct-with-fields.rs b/tests/expectations/tests/forward-inherit-struct-with-fields.rs index 2705ad0f59..05c6d3ee99 100644 --- a/tests/expectations/tests/forward-inherit-struct-with-fields.rs +++ b/tests/expectations/tests/forward-inherit-struct-with-fields.rs @@ -6,20 +6,20 @@ #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct Rooted { - pub _base: js_RootedBase, +pub struct js_RootedBase { + pub foo: *mut T, + pub next: *mut Rooted, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, } -impl Default for Rooted { +impl Default for js_RootedBase { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct js_RootedBase { - pub foo: *mut T, - pub next: *mut Rooted, +pub struct Rooted { + pub _base: js_RootedBase, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, } -impl Default for js_RootedBase { +impl Default for Rooted { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } diff --git a/tests/expectations/tests/forward-inherit-struct.rs b/tests/expectations/tests/forward-inherit-struct.rs index 28d8928baf..e3f2b225ea 100644 --- a/tests/expectations/tests/forward-inherit-struct.rs +++ b/tests/expectations/tests/forward-inherit-struct.rs @@ -4,6 +4,11 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct js_RootedBase { + pub _address: u8, +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct Rooted { @@ -12,8 +17,3 @@ pub struct Rooted { impl Default for Rooted { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } -#[repr(C)] -#[derive(Debug, Default, Copy, Clone)] -pub struct js_RootedBase { - pub _address: u8, -} diff --git a/tests/expectations/tests/issue-372.rs b/tests/expectations/tests/issue-372.rs index 8a11592475..6924d0a9d7 100644 --- a/tests/expectations/tests/issue-372.rs +++ b/tests/expectations/tests/issue-372.rs @@ -10,29 +10,6 @@ pub mod root { use self::super::root; #[repr(C)] #[derive(Debug, Copy)] - pub struct d { - pub m: root::i, - } - #[test] - fn bindgen_test_layout_d() { - assert_eq!(::std::mem::size_of::() , 24usize , concat ! ( - "Size of: " , stringify ! ( d ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( d ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const d ) ) . m as * const _ as usize } , - 0usize , concat ! ( - "Alignment of field: " , stringify ! ( d ) , "::" , - stringify ! ( m ) )); - } - impl Clone for d { - fn clone(&self) -> Self { *self } - } - impl Default for d { - fn default() -> Self { unsafe { ::std::mem::zeroed() } } - } - #[repr(C)] - #[derive(Debug, Copy)] pub struct i { pub j: *mut root::i, pub k: *mut root::i, @@ -66,6 +43,29 @@ pub mod root { impl Default for i { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } + #[repr(C)] + #[derive(Debug, Copy)] + pub struct d { + pub m: root::i, + } + #[test] + fn bindgen_test_layout_d() { + assert_eq!(::std::mem::size_of::() , 24usize , concat ! ( + "Size of: " , stringify ! ( d ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( d ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const d ) ) . m as * const _ as usize } , + 0usize , concat ! ( + "Alignment of field: " , stringify ! ( d ) , "::" , + stringify ! ( m ) )); + } + impl Clone for d { + fn clone(&self) -> Self { *self } + } + impl Default for d { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } + } #[repr(u32)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum n { diff --git a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs b/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs index 5c6d595b46..540b5e7feb 100644 --- a/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs +++ b/tests/expectations/tests/issue-584-stylo-template-analysis-panic.rs @@ -5,24 +5,6 @@ pub type RefPtr = T; -#[repr(C)] -#[derive(Debug, Copy)] -pub struct b { - pub _base: g, -} -#[test] -fn bindgen_test_layout_b() { - assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( - "Size of: " , stringify ! ( b ) )); - assert_eq! (::std::mem::align_of::() , 1usize , concat ! ( - "Alignment of " , stringify ! ( b ) )); -} -impl Clone for b { - fn clone(&self) -> Self { *self } -} -impl Default for b { - fn default() -> Self { unsafe { ::std::mem::zeroed() } } -} #[repr(C)] #[derive(Debug, Default, Copy)] pub struct A { @@ -75,6 +57,24 @@ impl Clone for g { impl Default for g { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct b { + pub _base: g, +} +#[test] +fn bindgen_test_layout_b() { + assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( + "Size of: " , stringify ! ( b ) )); + assert_eq! (::std::mem::align_of::() , 1usize , concat ! ( + "Alignment of " , stringify ! ( b ) )); +} +impl Clone for b { + fn clone(&self) -> Self { *self } +} +impl Default for b { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} extern "C" { #[link_name = "_Z25Servo_Element_GetSnapshotv"] pub fn Servo_Element_GetSnapshot() -> A; diff --git a/tests/expectations/tests/issue-888-enum-var-decl-jump.rs b/tests/expectations/tests/issue-888-enum-var-decl-jump.rs new file mode 100644 index 0000000000..e0330d5fec --- /dev/null +++ b/tests/expectations/tests/issue-888-enum-var-decl-jump.rs @@ -0,0 +1,36 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[allow(unused_imports)] + use self::super::root; + pub mod Halide { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy)] + pub struct Type { + pub _address: u8, + } + extern "C" { + #[link_name = "_ZN6Halide4Type1bE"] + pub static mut Type_b: root::a; + } + #[test] + fn bindgen_test_layout_Type() { + assert_eq!(::std::mem::size_of::() , 1usize , concat ! ( + "Size of: " , stringify ! ( Type ) )); + assert_eq! (::std::mem::align_of::() , 1usize , concat ! ( + "Alignment of " , stringify ! ( Type ) )); + } + impl Clone for Type { + fn clone(&self) -> Self { *self } + } + } + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] + pub enum a { } +} diff --git a/tests/expectations/tests/objc_class.rs b/tests/expectations/tests/objc_class.rs index 21f7c0d17e..31473c512c 100644 --- a/tests/expectations/tests/objc_class.rs +++ b/tests/expectations/tests/objc_class.rs @@ -9,13 +9,13 @@ extern crate objc; #[allow(non_camel_case_types)] pub type id = *mut objc::runtime::Object; +extern "C" { + #[link_name = "fooVar"] + pub static mut fooVar: *mut id; +} pub trait Foo { unsafe fn method(self); } impl Foo for id { unsafe fn method(self) { msg_send!(self , method) } } -extern "C" { - #[link_name = "fooVar"] - pub static mut fooVar: *mut id; -} diff --git a/tests/expectations/tests/opaque-tracing.rs b/tests/expectations/tests/opaque-tracing.rs index 8c80c83ae5..9d28d7c211 100644 --- a/tests/expectations/tests/opaque-tracing.rs +++ b/tests/expectations/tests/opaque-tracing.rs @@ -4,6 +4,10 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +extern "C" { + #[link_name = "_Z3fooP9Container"] + pub fn foo(c: *mut Container); +} #[repr(C)] #[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] pub struct Container { @@ -19,7 +23,3 @@ fn bindgen_test_layout_Container() { impl Clone for Container { fn clone(&self) -> Self { *self } } -extern "C" { - #[link_name = "_Z3fooP9Container"] - pub fn foo(c: *mut Container); -} diff --git a/tests/expectations/tests/template.rs b/tests/expectations/tests/template.rs index 91bdee729f..4033f07b78 100644 --- a/tests/expectations/tests/template.rs +++ b/tests/expectations/tests/template.rs @@ -192,6 +192,7 @@ impl Clone for RootedContainer { impl Default for RootedContainer { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } +pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; #[repr(C)] #[derive(Debug, Hash, PartialEq, Eq)] pub struct WithDtor { @@ -201,7 +202,6 @@ pub struct WithDtor { impl Default for WithDtor { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } -pub type WithDtorIntFwd = WithDtor<::std::os::raw::c_int>; #[repr(C)] #[derive(Debug, Hash, PartialEq, Eq)] pub struct PODButContainsDtor { @@ -268,22 +268,22 @@ impl Default for NestedBase { } #[repr(C)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct Incomplete { - pub d: T, +pub struct NestedContainer { + pub c: T, + pub nested: NestedReplaced, + pub inc: Incomplete, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, } -impl Default for Incomplete { +impl Default for NestedContainer { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NestedContainer { - pub c: T, - pub nested: NestedReplaced, - pub inc: Incomplete, +pub struct Incomplete { + pub d: T, pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell>, } -impl Default for NestedContainer { +impl Default for Incomplete { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } #[repr(C)] diff --git a/tests/expectations/tests/typeref.rs b/tests/expectations/tests/typeref.rs index cefd02ba9d..2bbdcbb148 100644 --- a/tests/expectations/tests/typeref.rs +++ b/tests/expectations/tests/typeref.rs @@ -4,25 +4,6 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[repr(C)] -pub struct nsFoo { - pub mBar: mozilla_StyleShapeSource, -} -#[test] -fn bindgen_test_layout_nsFoo() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( - "Size of: " , stringify ! ( nsFoo ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( nsFoo ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const nsFoo ) ) . mBar as * const _ as usize } - , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( nsFoo ) , "::" , - stringify ! ( mBar ) )); -} -impl Default for nsFoo { - fn default() -> Self { unsafe { ::std::mem::zeroed() } } -} #[repr(C)] #[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] pub struct mozilla_FragmentOrURL { @@ -99,6 +80,25 @@ impl Clone for Bar { impl Default for Bar { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } +#[repr(C)] +pub struct nsFoo { + pub mBar: mozilla_StyleShapeSource, +} +#[test] +fn bindgen_test_layout_nsFoo() { + assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( + "Size of: " , stringify ! ( nsFoo ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( nsFoo ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsFoo ) ) . mBar as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( nsFoo ) , "::" , + stringify ! ( mBar ) )); +} +impl Default for nsFoo { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} #[test] fn __bindgen_test_layout_mozilla_StyleShapeSource_open0_int_close0_instantiation() { assert_eq!(::std::mem::size_of::() , 8usize , diff --git a/tests/expectations/tests/typeref_1_0.rs b/tests/expectations/tests/typeref_1_0.rs index 0d24074362..a99df0ad9b 100644 --- a/tests/expectations/tests/typeref_1_0.rs +++ b/tests/expectations/tests/typeref_1_0.rs @@ -37,26 +37,6 @@ impl ::std::cmp::PartialEq for __BindgenUnionField { impl ::std::cmp::Eq for __BindgenUnionField { } #[repr(C)] #[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct nsFoo { - pub mBar: mozilla_StyleShapeSource, -} -#[test] -fn bindgen_test_layout_nsFoo() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( - "Size of: " , stringify ! ( nsFoo ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( nsFoo ) )); - assert_eq! (unsafe { - & ( * ( 0 as * const nsFoo ) ) . mBar as * const _ as usize } - , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( nsFoo ) , "::" , - stringify ! ( mBar ) )); -} -impl Clone for nsFoo { - fn clone(&self) -> Self { *self } -} -#[repr(C)] -#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] pub struct mozilla_FragmentOrURL { pub mIsLocalRef: bool, } @@ -127,6 +107,26 @@ impl Clone for Bar { impl Default for Bar { fn default() -> Self { unsafe { ::std::mem::zeroed() } } } +#[repr(C)] +#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] +pub struct nsFoo { + pub mBar: mozilla_StyleShapeSource, +} +#[test] +fn bindgen_test_layout_nsFoo() { + assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( + "Size of: " , stringify ! ( nsFoo ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( nsFoo ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const nsFoo ) ) . mBar as * const _ as usize } + , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( nsFoo ) , "::" , + stringify ! ( mBar ) )); +} +impl Clone for nsFoo { + fn clone(&self) -> Self { *self } +} #[test] fn __bindgen_test_layout_mozilla_StyleShapeSource_open0_int_close0_instantiation() { assert_eq!(::std::mem::size_of::() , 8usize , diff --git a/tests/expectations/tests/vtable_recursive_sig.rs b/tests/expectations/tests/vtable_recursive_sig.rs index f112e0cc01..ab2cd875a1 100644 --- a/tests/expectations/tests/vtable_recursive_sig.rs +++ b/tests/expectations/tests/vtable_recursive_sig.rs @@ -4,24 +4,6 @@ #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] -#[repr(C)] -#[derive(Debug, Copy)] -pub struct Derived { - pub _base: Base, -} -#[test] -fn bindgen_test_layout_Derived() { - assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( - "Size of: " , stringify ! ( Derived ) )); - assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( - "Alignment of " , stringify ! ( Derived ) )); -} -impl Clone for Derived { - fn clone(&self) -> Self { *self } -} -impl Default for Derived { - fn default() -> Self { unsafe { ::std::mem::zeroed() } } -} #[repr(C)] pub struct Base__bindgen_vtable(::std::os::raw::c_void); #[repr(C)] @@ -46,3 +28,21 @@ extern "C" { #[link_name = "_ZN4Base9AsDerivedEv"] pub fn Base_AsDerived(this: *mut ::std::os::raw::c_void) -> *mut Derived; } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Derived { + pub _base: Base, +} +#[test] +fn bindgen_test_layout_Derived() { + assert_eq!(::std::mem::size_of::() , 8usize , concat ! ( + "Size of: " , stringify ! ( Derived ) )); + assert_eq! (::std::mem::align_of::() , 8usize , concat ! ( + "Alignment of " , stringify ! ( Derived ) )); +} +impl Clone for Derived { + fn clone(&self) -> Self { *self } +} +impl Default for Derived { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} diff --git a/tests/headers/issue-888-enum-var-decl-jump.hpp b/tests/headers/issue-888-enum-var-decl-jump.hpp new file mode 100644 index 0000000000..d7f31b3e8d --- /dev/null +++ b/tests/headers/issue-888-enum-var-decl-jump.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --enable-cxx-namespaces + +namespace Halide { +struct Type; +} +typedef enum {} a; +namespace Halide { +struct Type { + static a b; +}; +}