Skip to content

Commit 8ecb50a

Browse files
committed
ir: Fix definitions outside of base class manually tracking the correct parent.
1 parent 179c1f6 commit 8ecb50a

File tree

3 files changed

+62
-19
lines changed

3 files changed

+62
-19
lines changed

src/ir/context.rs

+34
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ pub struct BindgenContext<'ctx> {
137137
/// Current module being traversed.
138138
current_module: ItemId,
139139

140+
/// A HashMap keyed on a type definition, and whose value is the parent id
141+
/// of the declaration.
142+
///
143+
/// This is used to handle the cases where the semantic and the lexical
144+
/// parents of the cursor differ, like when a nested class is defined
145+
/// outside of the parent class.
146+
semantic_parents: HashMap<clang::Cursor, ItemId>,
147+
140148
/// A stack with the current type declarations and types we're parsing. This
141149
/// is needed to avoid infinite recursion when parsing a type like:
142150
///
@@ -375,6 +383,7 @@ impl<'ctx> BindgenContext<'ctx> {
375383
next_item_id: ItemId(1),
376384
root_module: root_module.id(),
377385
current_module: root_module.id(),
386+
semantic_parents: Default::default(),
378387
currently_parsed_types: vec![],
379388
parsed_macros: Default::default(),
380389
replacements: Default::default(),
@@ -1187,6 +1196,31 @@ impl<'ctx> BindgenContext<'ctx> {
11871196
self.current_module
11881197
}
11891198

1199+
/// Add a semantic parent for a given type definition.
1200+
///
1201+
/// We do this from the type declaration, in order to be able to find the
1202+
/// correct type definition afterwards.
1203+
///
1204+
/// TODO(emilio): We could consider doing this only when
1205+
/// declaration.lexical_parent() != definition.lexical_parent(), but it's
1206+
/// not sure it's worth it.
1207+
pub fn add_semantic_parent(
1208+
&mut self,
1209+
definition: clang::Cursor,
1210+
parent_id: ItemId,
1211+
) {
1212+
self.semantic_parents.insert(definition, parent_id);
1213+
}
1214+
1215+
/// Returns a known semantic parent for a given definition.
1216+
pub fn known_semantic_parent(
1217+
&self,
1218+
definition: clang::Cursor
1219+
) -> Option<ItemId> {
1220+
self.semantic_parents.get(&definition).cloned()
1221+
}
1222+
1223+
11901224
/// Given a cursor pointing to the location of a template instantiation,
11911225
/// return a tuple of the form `(declaration_cursor, declaration_id,
11921226
/// num_expected_template_args)`.

src/ir/item.rs

+18-9
Original file line numberDiff line numberDiff line change
@@ -1197,19 +1197,28 @@ impl ClangItemParser for Item {
11971197
let definition = cursor.definition();
11981198
let applicable_cursor = definition.unwrap_or(cursor);
11991199

1200-
if definition.is_some() && definition != Some(cursor) {
1201-
return Ok(Item::from_ty_or_ref(
1202-
applicable_cursor.cur_type(),
1203-
cursor,
1204-
parent_id,
1205-
ctx,
1206-
));
1207-
}
1200+
1201+
let relevant_parent_id = match definition {
1202+
Some(definition) => {
1203+
if definition != cursor {
1204+
ctx.add_semantic_parent(definition, relevant_parent_id);
1205+
return Ok(Item::from_ty_or_ref(
1206+
applicable_cursor.cur_type(),
1207+
cursor,
1208+
parent_id,
1209+
ctx,
1210+
));
1211+
}
1212+
parent_id.or_else(|| ctx.known_semantic_parent(definition))
1213+
.unwrap_or(ctx.current_module())
1214+
}
1215+
None => relevant_parent_id,
1216+
};
12081217

12091218
match Item::from_ty(
12101219
&applicable_cursor.cur_type(),
12111220
applicable_cursor,
1212-
parent_id,
1221+
Some(relevant_parent_id),
12131222
ctx,
12141223
) {
12151224
Ok(ty) => return Ok(ty),

tests/expectations/tests/class_nested.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -55,22 +55,22 @@ impl Clone for A {
5555
}
5656
#[repr(C)]
5757
#[derive(Debug, Default, Copy, Hash, PartialEq, Eq)]
58-
pub struct C {
58+
pub struct A_C {
5959
pub baz: ::std::os::raw::c_int,
6060
}
6161
#[test]
62-
fn bindgen_test_layout_C() {
63-
assert_eq!(::std::mem::size_of::<C>() , 4usize , concat ! (
64-
"Size of: " , stringify ! ( C ) ));
65-
assert_eq! (::std::mem::align_of::<C>() , 4usize , concat ! (
66-
"Alignment of " , stringify ! ( C ) ));
62+
fn bindgen_test_layout_A_C() {
63+
assert_eq!(::std::mem::size_of::<A_C>() , 4usize , concat ! (
64+
"Size of: " , stringify ! ( A_C ) ));
65+
assert_eq! (::std::mem::align_of::<A_C>() , 4usize , concat ! (
66+
"Alignment of " , stringify ! ( A_C ) ));
6767
assert_eq! (unsafe {
68-
& ( * ( 0 as * const C ) ) . baz as * const _ as usize } ,
68+
& ( * ( 0 as * const A_C ) ) . baz as * const _ as usize } ,
6969
0usize , concat ! (
70-
"Alignment of field: " , stringify ! ( C ) , "::" , stringify
71-
! ( baz ) ));
70+
"Alignment of field: " , stringify ! ( A_C ) , "::" ,
71+
stringify ! ( baz ) ));
7272
}
73-
impl Clone for C {
73+
impl Clone for A_C {
7474
fn clone(&self) -> Self { *self }
7575
}
7676
extern "C" {

0 commit comments

Comments
 (0)