diff options
author | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-09-21 23:16:05 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <ecoal95@gmail.com> | 2016-09-21 23:37:14 +0200 |
commit | 6ed0253913afc0c0258eaedfb27d87322250f2b2 (patch) | |
tree | 336946be39044850a801af21fbff5dfe7cff0449 | |
parent | 506531522c5910717d89fc3bfdf07d0cdf65485a (diff) |
Index unnamed types by canonical declaration.
This fixes union_with_nesting.h
-rw-r--r-- | src/ir/context.rs | 45 | ||||
-rw-r--r-- | tests/expectations/struct_with_nesting.rs | 20 | ||||
-rw-r--r-- | tests/expectations/union_with_nesting.rs | 19 |
3 files changed, 71 insertions, 13 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs index f3c24db2..559dd2ba 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -14,6 +14,18 @@ use syntax::ext::base::ExtCtxt; use parse::ClangItemParser; use BindgenOptions; +/// A key used to index a resolved type, so we only process it once. +/// +/// This is almost always a USR string (an unique identifier generated by +/// clang), but it can also be the canonical declaration if the type is unnamed, +/// in which case clang may generate the same USR for multiple nested unnamed +/// types. +#[derive(Eq, PartialEq, Hash, Debug)] +enum TypeKey { + USR(String), + Declaration(Cursor), +} + // This is just convenience to avoid creating a manual debug impl for the // context. struct GenContext<'ctx>(ExtCtxt<'ctx>); @@ -35,7 +47,7 @@ pub struct BindgenContext<'ctx> { /// Clang USR to type map. This is needed to be able to associate types with /// item ids during parsing. - types: HashMap<String, ItemId>, + types: HashMap<TypeKey, ItemId>, /// A cursor to module map. Similar reason than above. modules: HashMap<Cursor, ItemId>, @@ -129,9 +141,13 @@ impl<'ctx> BindgenContext<'ctx> { let id = item.id(); let is_type = item.kind().is_type(); + let is_unnamed = is_type && item.expect_type().name().is_none(); let old_item = self.items.insert(id, item); assert!(old_item.is_none(), "Inserted type twice?"); + // Unnamed items can have an USR, but they can't be referenced from + // other sites explicitly and the USR can match if the unnamed items are + // nested, so don't bother tracking them. if is_type && declaration.is_some() { let mut declaration = declaration.unwrap(); if !declaration.is_valid() { @@ -143,8 +159,6 @@ impl<'ctx> BindgenContext<'ctx> { } } declaration = declaration.canonical(); - - if !declaration.is_valid() { // This could happen, for example, with types like `int*` or // similar. @@ -156,12 +170,17 @@ impl<'ctx> BindgenContext<'ctx> { return; } - if let Some(usr) = declaration.usr() { - let old = self.types.insert(usr, id); - debug_assert_eq!(old, None); + let key = if is_unnamed { + TypeKey::Declaration(declaration) + } else if let Some(usr) = declaration.usr() { + TypeKey::USR(usr) } else { error!("Valid declaration with no USR: {:?}, {:?}", declaration, location); - } + return; + }; + + let old = self.types.insert(key, id); + debug_assert_eq!(old, None); } } @@ -503,10 +522,14 @@ impl<'ctx> BindgenContext<'ctx> { let canonical_declaration = declaration.canonical(); if canonical_declaration.is_valid() { let id = - canonical_declaration - .usr() - .and_then(|usr| self.types.get(&usr)) - .map(|id| *id); + self.types.get(&TypeKey::Declaration(canonical_declaration)) + .map(|id| *id) + .or_else(|| { + canonical_declaration.usr().and_then(|usr| { + self.types.get(&TypeKey::USR(usr)) + }) + .map(|id| *id) + }); if let Some(id) = id { debug!("Already resolved ty {:?}, {:?}, {:?} {:?}", id, declaration, ty, location); diff --git a/tests/expectations/struct_with_nesting.rs b/tests/expectations/struct_with_nesting.rs index 75cfecec..9eeeb56e 100644 --- a/tests/expectations/struct_with_nesting.rs +++ b/tests/expectations/struct_with_nesting.rs @@ -35,7 +35,7 @@ pub struct foo { pub struct foo__bindgen_ty_bindgen_id_4 { pub b: __BindgenUnionField<::std::os::raw::c_uint>, pub __bindgen_anon_1: __BindgenUnionField<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_7>, - pub __bindgen_anon_2: __BindgenUnionField<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_7>, + pub __bindgen_anon_2: __BindgenUnionField<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12>, pub bindgen_union_field: u32, } #[repr(C)] @@ -54,6 +54,24 @@ fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_7() { impl Clone for foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_7 { fn clone(&self) -> Self { *self } } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12 { + pub d1: ::std::os::raw::c_uchar, + pub d2: ::std::os::raw::c_uchar, + pub d3: ::std::os::raw::c_uchar, + pub d4: ::std::os::raw::c_uchar, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12() { + assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12>() + , 4usize); + assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12>() + , 1usize); +} +impl Clone for foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_12 { + fn clone(&self) -> Self { *self } +} #[test] fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4() { assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_4>() , diff --git a/tests/expectations/union_with_nesting.rs b/tests/expectations/union_with_nesting.rs index 7534cf81..d7fc780a 100644 --- a/tests/expectations/union_with_nesting.rs +++ b/tests/expectations/union_with_nesting.rs @@ -35,7 +35,7 @@ pub struct foo { #[derive(Debug, Copy)] pub struct foo__bindgen_ty_bindgen_id_4 { pub __bindgen_anon_1: foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_5, - pub __bindgen_anon_2: foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_5, + pub __bindgen_anon_2: foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10, } #[repr(C)] #[derive(Debug, Copy)] @@ -54,6 +54,23 @@ fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_5() { impl Clone for foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_5 { fn clone(&self) -> Self { *self } } +#[repr(C)] +#[derive(Debug, Copy)] +pub struct foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10 { + pub c1: __BindgenUnionField<::std::os::raw::c_ushort>, + pub c2: __BindgenUnionField<::std::os::raw::c_ushort>, + pub bindgen_union_field: u16, +} +#[test] +fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10() { + assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10>() + , 2usize); + assert_eq!(::std::mem::align_of::<foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10>() + , 2usize); +} +impl Clone for foo__bindgen_ty_bindgen_id_4__bindgen_ty_bindgen_id_10 { + fn clone(&self) -> Self { *self } +} #[test] fn bindgen_test_layout_foo__bindgen_ty_bindgen_id_4() { assert_eq!(::std::mem::size_of::<foo__bindgen_ty_bindgen_id_4>() , |