diff --git a/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs index 58644e053d..137927a302 100644 --- a/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs +++ b/bindgen-tests/tests/expectations/tests/opaque-template-instantiation-namespaced.rs @@ -86,16 +86,16 @@ pub mod root { "Offset of field: ContainsOpaqueInstantiation::opaque", ][::std::mem::offset_of!(ContainsOpaqueInstantiation, opaque) - 0usize]; }; + #[allow(clippy::unnecessary_operation, clippy::identity_op)] + const _: () = { + [ + "Size of template specialization: Template_open0_Foo_close0", + ][::std::mem::size_of::>() + - 1usize]; + [ + "Align of template specialization: Template_open0_Foo_close0", + ][::std::mem::align_of::>() + - 1usize]; + }; } - #[allow(clippy::unnecessary_operation, clippy::identity_op)] - const _: () = { - [ - "Size of template specialization: Template_open0_Foo_close0", - ][::std::mem::size_of::>() - - 1usize]; - [ - "Align of template specialization: Template_open0_Foo_close0", - ][::std::mem::align_of::>() - - 1usize]; - }; } diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 8da10ff051..d8333335a3 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -500,6 +500,36 @@ impl Item { return false; } + // Skip duplicate type aliases. + // If this item is a type alias or resolved ref, and its ultimate target + // has the same canonical path and will also be generated, skip this one. + if let ItemKind::Type(ty) = self.kind() { + match ty.kind() { + TypeKind::Alias(target_id) | + TypeKind::ResolvedTypeRef(target_id) => { + let direct_target = ctx.resolve_item(*target_id); + // Check if the direct target has the same path and will be generated. + // If so, skip generating this alias/ref because the direct target + // will either be generated or skipped in favour of its target. + if direct_target.id() != self.id() && + direct_target.canonical_path(ctx) == + self.canonical_path(ctx) && + ctx.codegen_items().contains(&direct_target.id()) + { + debug!( + "::process_before_codegen: Skipping duplicate alias {:?} because its direct target {:?} has the same path and will be generated", + self.id(), + direct_target.id() + ); + // Mark as seen so we don't process it again if reachable through another path + result.set_seen(self.id()); + return false; + } + } + _ => {} + } + } + if !ctx.codegen_items().contains(&self.id()) { // TODO(emilio, #453): Figure out what to do when this happens // legitimately, we could track the opaque stuff and disable the diff --git a/bindgen/ir/context.rs b/bindgen/ir/context.rs index 3f9e16ac9b..4914dc7961 100644 --- a/bindgen/ir/context.rs +++ b/bindgen/ir/context.rs @@ -783,17 +783,22 @@ If you encounter an error missing from this list, please file an issue or a PR!" assert_ne!(item.id(), self.root_module); assert!(self.resolve_item_fallible(item.id()).is_none()); - if let Some(ref mut parent) = self.items[item.parent_id().0] { - if let Some(module) = parent.as_module_mut() { + let mut ancestor_id = item.parent_id(); + while let Some(ref mut ancestor_item) = self.items[ancestor_id.0] { + if let Some(module) = ancestor_item.as_module_mut() { debug!( - "add_item_to_module: adding {:?} as child of parent module {:?}", + "add_item_to_module: adding {:?} as child of ancestor module {:?}", item.id(), - item.parent_id() + ancestor_id ); - module.children_mut().insert(item.id()); return; } + + ancestor_id = ancestor_item.parent_id(); + if ancestor_id == ancestor_item.id() { + break; + } } debug!( diff --git a/bindgen/ir/template.rs b/bindgen/ir/template.rs index 7f3667879d..c4a6486e83 100644 --- a/bindgen/ir/template.rs +++ b/bindgen/ir/template.rs @@ -215,6 +215,7 @@ impl TemplateInstantiation { /// Parse a `TemplateInstantiation` from a clang `Type`. pub(crate) fn from_ty( ty: &clang::Type, + parent_id: Option, ctx: &mut BindgenContext, ) -> Option { use clang_sys::*; @@ -228,13 +229,15 @@ impl TemplateInstantiation { args.chain(canonical_args.skip(arg_count)) .filter(|t| t.kind() != CXType_Invalid) .map(|t| { - Item::from_ty_or_ref(t, t.declaration(), None, ctx) + Item::from_ty_or_ref(t, t.declaration(), parent_id, ctx) }) .collect() } None => args .filter(|t| t.kind() != CXType_Invalid) - .map(|t| Item::from_ty_or_ref(t, t.declaration(), None, ctx)) + .map(|t| { + Item::from_ty_or_ref(t, t.declaration(), parent_id, ctx) + }) .collect(), }); diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs index baaa4a4907..f4a9f23187 100644 --- a/bindgen/ir/ty.rs +++ b/bindgen/ir/ty.rs @@ -746,7 +746,7 @@ impl Type { (ty.template_args().is_some() && ty_kind != CXType_Typedef) { // This is a template instantiation. - match TemplateInstantiation::from_ty(ty, ctx) { + match TemplateInstantiation::from_ty(ty, parent_id, ctx) { Some(inst) => TypeKind::TemplateInstantiation(inst), None => TypeKind::Opaque, } @@ -1058,7 +1058,7 @@ impl Type { CXType_Typedef => { let inner = cursor.typedef_type().expect("Not valid Type?"); let inner_id = - Item::from_ty_or_ref(inner, location, None, ctx); + Item::from_ty_or_ref(inner, location, parent_id, ctx); if inner_id == potential_id { warn!( "Generating opaque type instead of self-referential \