summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-09-04 12:51:15 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-09-04 12:51:15 +0200
commit8ecb50a99ec7bf8630f2c7b7163aa3364a9b87c0 (patch)
tree1fc374f6602bc5f6249644f38be733356a47ed4d
parent179c1f6b19eccc13eb2976bd3c2ae96c88d17adb (diff)
ir: Fix definitions outside of base class manually tracking the correct parent.
-rw-r--r--src/ir/context.rs34
-rw-r--r--src/ir/item.rs27
-rw-r--r--tests/expectations/tests/class_nested.rs20
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" {