diff --git a/bindgen-tests/tests/expectations/tests/3119_overlapping_alias_comment.rs b/bindgen-tests/tests/expectations/tests/3119_overlapping_alias_comment.rs new file mode 100644 index 0000000000..a2562193b5 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/3119_overlapping_alias_comment.rs @@ -0,0 +1,8 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +/** This is a forward declared struct alias with overlapping names + and documentation.*/ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Struct { + _unused: [u8; 0], +} diff --git a/bindgen-tests/tests/headers/3119_overlapping_alias_comment.h b/bindgen-tests/tests/headers/3119_overlapping_alias_comment.h new file mode 100644 index 0000000000..daa6c83df3 --- /dev/null +++ b/bindgen-tests/tests/headers/3119_overlapping_alias_comment.h @@ -0,0 +1,7 @@ +// bindgen-flags: --no-layout-tests + +/** + * This is a forward declared struct alias with overlapping names + * and documentation. + */ +typedef struct Struct Struct; diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index f58a234117..3cceba003d 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -2410,7 +2410,12 @@ impl CodeGenerator for CompInfo { let mut needs_debug_impl = false; let mut needs_partialeq_impl = false; let needs_flexarray_impl = flex_array_generic.is_some(); - if let Some(comment) = item.comment(ctx) { + let type_id = item.id().expect_type_id(ctx); + + if let Some(comment) = item + .comment(ctx) + .or_else(|| Self::get_typedef_fallback_comment(ctx, &type_id)) + { attributes.push(attributes::doc(&comment)); } @@ -2987,6 +2992,48 @@ impl CompInfo { } } } + + /// Use a fallback comment from a type alias to this type if necessary + /// + /// The documentation for a type could get lost in the following circumstances: + /// + /// - We have a type and a type alias with the same canonical path + /// - The Documentation is only associated with the type alias + /// + /// In this case bindgen will not generate the type alias and the documentation would be lost. + /// To avoid this, we check here if there is any type alias to this type, which has + /// the same canonical path and return the comment as a fallback, if our type does + /// not have documentation. + fn get_typedef_fallback_comment( + ctx: &BindgenContext, + type_id: &crate::ir::context::TypeId, + ) -> Option { + if !ctx.options().generate_comments { + return None; + } + let type_alias_comment = ctx + .items() + .filter(|(_id, alias)| { + let Some(this_ty) = alias.as_type() else { + return false; + }; + let TypeKind::Alias(alias_to) = this_ty.kind() else { + return false; + }; + // + match ctx.resolve_type(*alias_to).kind() { + TypeKind::ResolvedTypeRef(resolved_typeid) => { + resolved_typeid == type_id && + alias.canonical_path(ctx) == + type_id.canonical_path(ctx) + } + _ => false, + } + }) + .filter_map(|(_id, item)| item.comment(ctx)); + let alias_comment: Vec = type_alias_comment.collect(); + alias_comment.get(0).cloned() + } } impl Method {