diff --git a/src/bindgen/ir/global.rs b/src/bindgen/ir/global.rs index 47c996055..82a1756e1 100644 --- a/src/bindgen/ir/global.rs +++ b/src/bindgen/ir/global.rs @@ -4,8 +4,6 @@ use std::io::Write; -use syn::ext::IdentExt; - use crate::bindgen::cdecl; use crate::bindgen::config::Config; use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver; @@ -26,7 +24,11 @@ pub struct Static { } impl Static { - pub fn load(item: &syn::ItemStatic, mod_cfg: Option<&Cfg>) -> Result { + pub fn load( + path: Path, + item: &syn::ItemStatic, + mod_cfg: Option<&Cfg>, + ) -> Result { let ty = Type::load(&item.ty)?; if ty.is_none() { @@ -34,7 +36,7 @@ impl Static { } Ok(Static::new( - Path::new(item.ident.unraw().to_string()), + path, ty.unwrap(), item.mutability.is_some(), Cfg::append(mod_cfg, Cfg::load(&item.attrs)), diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs index e8add192a..9cd6a54a4 100644 --- a/src/bindgen/parser.rs +++ b/src/bindgen/parser.rs @@ -18,7 +18,7 @@ use crate::bindgen::ir::{ AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams, ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union, }; -use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers}; +use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemHelpers}; const STD_CRATES: &[&str] = &[ "std", @@ -643,7 +643,6 @@ impl Parse { item, Some(self_type), &item.sig, - &item.vis, &item.attrs, ) } @@ -665,7 +664,6 @@ impl Parse { item, None, &item.sig, - &item.vis, &item.attrs, ); } @@ -677,10 +675,9 @@ impl Parse { binding_crate_name: &str, crate_name: &str, mod_cfg: Option<&Cfg>, - named_symbol: &dyn SynItemFnHelpers, + named_symbol: &dyn SynItemHelpers, self_type: Option<&Path>, sig: &syn::Signature, - vis: &syn::Visibility, attrs: &[syn::Attribute], ) { if !config @@ -707,53 +704,29 @@ impl Parse { let is_extern_c = sig.abi.is_omitted() || sig.abi.is_c(); let exported_name = named_symbol.exported_name(); - if let syn::Visibility::Public(_) = vis { - match (is_extern_c, exported_name) { - (true, Some(exported_name)) => { - let path = Path::new(exported_name); - match Function::load(path, self_type, sig, false, attrs, mod_cfg) { - Ok(func) => { - info!("Take {}.", loggable_item_name()); - self.functions.push(func); - } - Err(msg) => { - error!("Cannot use fn {} ({}).", loggable_item_name(), msg); - } + match (is_extern_c, exported_name) { + (true, Some(exported_name)) => { + let path = Path::new(exported_name); + match Function::load(path, self_type, sig, false, attrs, mod_cfg) { + Ok(func) => { + info!("Take {}.", loggable_item_name()); + self.functions.push(func); + } + Err(msg) => { + error!("Cannot use fn {} ({}).", loggable_item_name(), msg); } } - (true, None) => { - warn!( - "Skipping {} - (not `no_mangle`, and has no `export_name` attribute)", - loggable_item_name() - ); - } - (false, Some(_exported_name)) => { - warn!("Skipping {} - (not `extern \"C\"`", loggable_item_name()); - } - (false, None) => {} } - } else { - match (is_extern_c, exported_name) { - (true, Some(..)) => { - warn!( - "Skipping {} - (not `pub` but is `extern \"C\"` and `no_mangle`)", - loggable_item_name() - ); - } - (true, None) => { - warn!( - "Skipping {} - (not `pub` but is `extern \"C\"`)", - loggable_item_name() - ); - } - (false, Some(..)) => { - warn!( - "Skipping {} - (not `pub` but is `no_mangle`)", - loggable_item_name() - ); - } - (false, None) => {} + (true, None) => { + warn!( + "Skipping {} - (not `no_mangle`, and has no `export_name` attribute)", + loggable_item_name() + ); } + (false, Some(_exported_name)) => { + warn!("Skipping {} - (not `extern \"C\"`", loggable_item_name()); + } + (false, None) => {} } } @@ -892,27 +865,18 @@ impl Parse { return; } - if let syn::Visibility::Public(_) = item.vis { - if item.is_no_mangle() { - match Static::load(item, mod_cfg) { - Ok(constant) => { - info!("Take {}::{}.", crate_name, &item.ident); - - self.globals.try_insert(constant); - } - Err(msg) => { - warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg); - } + if let Some(exported_name) = item.exported_name() { + let path = Path::new(exported_name); + match Static::load(path, item, mod_cfg) { + Ok(constant) => { + info!("Take {}::{}.", crate_name, &item.ident); + self.globals.try_insert(constant); + } + Err(msg) => { + warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg); } } - } - - // TODO - if let syn::Visibility::Public(_) = item.vis { } else { - warn!("Skip {}::{} - (not `pub`).", crate_name, &item.ident); - } - if !item.is_no_mangle() { warn!("Skip {}::{} - (not `no_mangle`).", crate_name, &item.ident); } } diff --git a/src/bindgen/utilities.rs b/src/bindgen/utilities.rs index ae3ee6032..bea1d99a4 100644 --- a/src/bindgen/utilities.rs +++ b/src/bindgen/utilities.rs @@ -30,11 +30,11 @@ where } } -pub trait SynItemFnHelpers: SynAttributeHelpers { +pub trait SynItemHelpers: SynAttributeHelpers { fn exported_name(&self) -> Option; } -impl SynItemFnHelpers for syn::ItemFn { +impl SynItemHelpers for syn::ItemFn { fn exported_name(&self) -> Option { self.attrs .attr_name_value_lookup("export_name") @@ -48,7 +48,7 @@ impl SynItemFnHelpers for syn::ItemFn { } } -impl SynItemFnHelpers for syn::ImplItemMethod { +impl SynItemHelpers for syn::ImplItemMethod { fn exported_name(&self) -> Option { self.attrs .attr_name_value_lookup("export_name") @@ -62,6 +62,20 @@ impl SynItemFnHelpers for syn::ImplItemMethod { } } +impl SynItemHelpers for syn::ItemStatic { + fn exported_name(&self) -> Option { + self.attrs + .attr_name_value_lookup("export_name") + .or_else(|| { + if self.is_no_mangle() { + Some(self.ident.unraw().to_string()) + } else { + None + } + }) + } +} + /// Returns whether this attribute causes us to skip at item. This basically /// checks for `#[cfg(test)]`, `#[test]`, `/// cbindgen::ignore` and /// variations thereof. diff --git a/tests/expectations/non_pub_extern.c b/tests/expectations/non_pub_extern.c new file mode 100644 index 000000000..779000d65 --- /dev/null +++ b/tests/expectations/non_pub_extern.c @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +extern const uint32_t FIRST; + +extern const uint32_t RENAMED; + +void first(void); + +void renamed(void); diff --git a/tests/expectations/non_pub_extern.compat.c b/tests/expectations/non_pub_extern.compat.c new file mode 100644 index 000000000..549345195 --- /dev/null +++ b/tests/expectations/non_pub_extern.compat.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +extern const uint32_t FIRST; + +extern const uint32_t RENAMED; + +void first(void); + +void renamed(void); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus diff --git a/tests/expectations/non_pub_extern.cpp b/tests/expectations/non_pub_extern.cpp new file mode 100644 index 000000000..c931fbc39 --- /dev/null +++ b/tests/expectations/non_pub_extern.cpp @@ -0,0 +1,17 @@ +#include +#include +#include +#include +#include + +extern "C" { + +extern const uint32_t FIRST; + +extern const uint32_t RENAMED; + +void first(); + +void renamed(); + +} // extern "C" diff --git a/tests/expectations/non_pub_extern.pyx b/tests/expectations/non_pub_extern.pyx new file mode 100644 index 000000000..112841ffd --- /dev/null +++ b/tests/expectations/non_pub_extern.pyx @@ -0,0 +1,15 @@ +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t +cdef extern from *: + ctypedef bint bool + ctypedef struct va_list + +cdef extern from *: + + extern const uint32_t FIRST; + + extern const uint32_t RENAMED; + + void first(); + + void renamed(); diff --git a/tests/rust/non_pub_extern.rs b/tests/rust/non_pub_extern.rs new file mode 100644 index 000000000..4174324d7 --- /dev/null +++ b/tests/rust/non_pub_extern.rs @@ -0,0 +1,13 @@ +#[no_mangle] +static FIRST: u32 = 10; + +#[export_name = "RENAMED"] +static SECOND: u32 = 42; + +#[no_mangle] +extern "C" fn first() +{ } + +#[export_name = "renamed"] +extern fn second() +{ }