Skip to content

Commit

Permalink
ir: Fix definitions outside of base class manually tracking the corre…
Browse files Browse the repository at this point in the history
…ct parent.
  • Loading branch information
emilio committed Sep 4, 2017
1 parent 179c1f6 commit 8ecb50a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 19 deletions.
34 changes: 34 additions & 0 deletions src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
///
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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)`.
Expand Down
27 changes: 18 additions & 9 deletions src/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
20 changes: 10 additions & 10 deletions tests/expectations/tests/class_nested.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down

0 comments on commit 8ecb50a

Please sign in to comment.