diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-09-04 12:51:15 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-09-04 12:51:15 +0200 |
commit | 8ecb50a99ec7bf8630f2c7b7163aa3364a9b87c0 (patch) | |
tree | 1fc374f6602bc5f6249644f38be733356a47ed4d | |
parent | 179c1f6b19eccc13eb2976bd3c2ae96c88d17adb (diff) |
ir: Fix definitions outside of base class manually tracking the correct parent.
-rw-r--r-- | src/ir/context.rs | 34 | ||||
-rw-r--r-- | src/ir/item.rs | 27 | ||||
-rw-r--r-- | tests/expectations/tests/class_nested.rs | 20 |
3 files changed, 62 insertions, 19 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs index 788c3f98..3bb8b5d9 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<clang::Cursor, ItemId>, + /// 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<ItemId> { + 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 e3c5d4a7..0dac1287 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1197,19 +1197,28 @@ impl ClangItemParser for Item { let definition = cursor.definition(); let applicable_cursor = definition.unwrap_or(cursor); - if definition.is_some() && definition != Some(cursor) { - return Ok(Item::from_ty_or_ref( - applicable_cursor.cur_type(), - cursor, - parent_id, - ctx, - )); - } + + 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 cb23d6dd..a874d6b8 100644 --- a/tests/expectations/tests/class_nested.rs +++ b/tests/expectations/tests/class_nested.rs @@ -55,22 +55,22 @@ impl Clone for A { } #[repr(C)] #[derive(Debug, Default, Copy, Hash, PartialEq, Eq)] -pub struct C { +pub struct A_C { pub baz: ::std::os::raw::c_int, } #[test] -fn bindgen_test_layout_C() { - assert_eq!(::std::mem::size_of::<C>() , 4usize , concat ! ( - "Size of: " , stringify ! ( C ) )); - assert_eq! (::std::mem::align_of::<C>() , 4usize , concat ! ( - "Alignment of " , stringify ! ( C ) )); +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 C ) ) . baz as * const _ as usize } , + & ( * ( 0 as * const A_C ) ) . baz as * const _ as usize } , 0usize , concat ! ( - "Alignment of field: " , stringify ! ( C ) , "::" , stringify - ! ( baz ) )); + "Alignment of field: " , stringify ! ( A_C ) , "::" , + stringify ! ( baz ) )); } -impl Clone for C { +impl Clone for A_C { fn clone(&self) -> Self { *self } } extern "C" { |