From 2269982ab9a921a4d3e57d92090c8703b34fdd33 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 30 Oct 2024 22:42:38 -0400 Subject: [PATCH] Use `field_visibility` callback for new-type aliases The `field_visibility` callback is now called in case of alias new-type and new-type-deref with the type name and field_name set to `"0"` --- .../tests/expectations/tests/issue-2966.rs | 10 +++++++ bindgen-tests/tests/headers/issue-2966.h | 6 +++++ bindgen-tests/tests/parse_callbacks/mod.rs | 27 +++++++++++++++++-- bindgen/codegen/mod.rs | 12 +++++++-- 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 bindgen-tests/tests/expectations/tests/issue-2966.rs create mode 100644 bindgen-tests/tests/headers/issue-2966.h diff --git a/bindgen-tests/tests/expectations/tests/issue-2966.rs b/bindgen-tests/tests/expectations/tests/issue-2966.rs new file mode 100644 index 0000000000..bfdcbd9e2f --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/issue-2966.rs @@ -0,0 +1,10 @@ +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct pub_var1(pub *const ::std::os::raw::c_char); +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct pubcrate_var2(pub(crate) *const ::std::os::raw::c_char); +#[repr(transparent)] +#[derive(Debug, Copy, Clone)] +pub struct private_var3(*const ::std::os::raw::c_char); diff --git a/bindgen-tests/tests/headers/issue-2966.h b/bindgen-tests/tests/headers/issue-2966.h new file mode 100644 index 0000000000..3f00dec65d --- /dev/null +++ b/bindgen-tests/tests/headers/issue-2966.h @@ -0,0 +1,6 @@ +// bindgen-flags: --default-alias-style=new_type +// bindgen-parse-callbacks: type-visibility + +typedef const char * pub_var1; +typedef const char * pubcrate_var2; +typedef const char * private_var3; diff --git a/bindgen-tests/tests/parse_callbacks/mod.rs b/bindgen-tests/tests/parse_callbacks/mod.rs index ee31d56e49..9f4b04a202 100644 --- a/bindgen-tests/tests/parse_callbacks/mod.rs +++ b/bindgen-tests/tests/parse_callbacks/mod.rs @@ -93,8 +93,8 @@ struct FieldVisibility { } /// Implements the `field_visibility` function of the trait by checking if the -/// field name starts with `private_`. If it does it makes it private, if it -/// doesn't it makes it public, taking into account the default visibility. +/// field name starts with `private_`. If it does, it makes it private, if it +/// doesn't, it makes it public, taking into account the default visibility. impl ParseCallbacks for FieldVisibility { fn field_visibility( &self, @@ -113,6 +113,28 @@ impl ParseCallbacks for FieldVisibility { } } +#[derive(Debug)] +struct TypeVisibility; + +/// Implements the `field_visibility` function of the trait by checking the +/// type name. Depending on name prefix, it will return a different visibility. +impl ParseCallbacks for TypeVisibility { + fn field_visibility( + &self, + FieldInfo { type_name, .. }: FieldInfo, + ) -> Option { + if type_name.starts_with("private_") { + Some(FieldVisibilityKind::Private) + } else if type_name.starts_with("pubcrate_") { + Some(FieldVisibilityKind::PublicCrate) + } else if type_name.starts_with("pub_") { + Some(FieldVisibilityKind::Public) + } else { + None + } + } +} + #[derive(Debug)] pub(super) struct WrapAsVariadicFn; @@ -129,6 +151,7 @@ pub fn lookup(cb: &str) -> Box { Box::new(BlocklistedTypeImplementsTrait) } "wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn), + "type-visibility" => Box::new(TypeVisibility), call_back => { if let Some(prefix) = call_back.strip_prefix("remove-function-prefix-") diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index ff6daac362..4cab877362 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -1100,13 +1100,21 @@ impl CodeGenerator for Type { }); } - let access_spec = - access_specifier(ctx.options().default_visibility); tokens.append_all(match alias_style { AliasVariation::TypeAlias => quote! { = #inner_rust_type ; }, AliasVariation::NewType | AliasVariation::NewTypeDeref => { + let visibility = ctx + .options() + .last_callback(|cb| { + cb.field_visibility(FieldInfo { + type_name: &item.canonical_name(ctx), + field_name: "0", + }) + }) + .unwrap_or(ctx.options().default_visibility); + let access_spec = access_specifier(visibility); quote! { (#access_spec #inner_rust_type) ; }