summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmil Gardström <emil.gardstrom@gmail.com>2022-02-25 20:13:47 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2022-03-15 04:00:08 +0100
commit9689aecbfe45c9ba18d6d95de3cb903b1740b8cf (patch)
tree7f30874b311f9c48954b5be631c9748e49beac6b
parent310f7f877042f0858cd01fb1c326a41d23bd821c (diff)
add attributes to dynamic functions
this includes comments and must_use annotations
-rw-r--r--src/codegen/dyngen.rs3
-rw-r--r--src/codegen/mod.rs29
-rw-r--r--tests/expectations/tests/dynamic_loading_attributes.rs56
-rw-r--r--tests/headers/dynamic_loading_attributes.h11
4 files changed, 89 insertions, 10 deletions
diff --git a/src/codegen/dyngen.rs b/src/codegen/dyngen.rs
index 71c4dab1..26cfe5cc 100644
--- a/src/codegen/dyngen.rs
+++ b/src/codegen/dyngen.rs
@@ -112,6 +112,7 @@ impl DynamicItems {
}
}
+ #[allow(clippy::too_many_arguments)]
pub fn push(
&mut self,
ident: Ident,
@@ -122,6 +123,7 @@ impl DynamicItems {
args_identifiers: Vec<proc_macro2::TokenStream>,
ret: proc_macro2::TokenStream,
ret_ty: proc_macro2::TokenStream,
+ attributes: Vec<proc_macro2::TokenStream>,
) {
if !is_variadic {
assert_eq!(args.len(), args_identifiers.len());
@@ -153,6 +155,7 @@ impl DynamicItems {
// access the function pointer so that the user can call it just fine.
if !is_variadic {
self.struct_implementation.push(quote! {
+ #(#attributes)*
pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
#call_body
}
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index b988a516..7c8e2646 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -3907,6 +3907,8 @@ impl CodeGenerator for Function {
Linkage::External => {}
}
+ #[allow(clippy::needless_late_init)]
+ let is_dynamic_function;
// Pure virtual methods have no actual symbol, so we can't generate
// something meaningful for them.
match self.kind() {
@@ -3915,7 +3917,14 @@ impl CodeGenerator for Function {
{
return None;
}
- _ => {}
+ FunctionKind::Function => {
+ // If we're generating for dynamic loading, some attributes can not be emitted.
+ is_dynamic_function =
+ ctx.options().dynamic_library_name.is_some()
+ }
+ _ => {
+ is_dynamic_function = false;
+ }
}
// Similar to static member variables in a class template, we can't
@@ -3958,7 +3967,6 @@ impl CodeGenerator for Function {
{
attributes.push(attributes::must_use());
}
-
if let Some(comment) = item.comment(ctx) {
attributes.push(attributes::doc(comment));
}
@@ -3995,11 +4003,13 @@ impl CodeGenerator for Function {
}
let link_name = mangled_name.unwrap_or(name);
- if !utils::names_will_be_identical_after_mangling(
- &canonical_name,
- link_name,
- Some(abi),
- ) {
+ if !is_dynamic_function &&
+ !utils::names_will_be_identical_after_mangling(
+ &canonical_name,
+ link_name,
+ Some(abi),
+ )
+ {
attributes.push(attributes::link_name(link_name));
}
@@ -4021,9 +4031,7 @@ impl CodeGenerator for Function {
};
// If we're doing dynamic binding generation, add to the dynamic items.
- if ctx.options().dynamic_library_name.is_some() &&
- self.kind() == FunctionKind::Function
- {
+ if is_dynamic_function {
let args_identifiers =
utils::fnsig_argument_identifiers(ctx, signature);
let return_item = ctx.resolve_item(signature.return_type());
@@ -4040,6 +4048,7 @@ impl CodeGenerator for Function {
args_identifiers,
ret,
ret_ty,
+ attributes,
);
} else {
result.push(tokens);
diff --git a/tests/expectations/tests/dynamic_loading_attributes.rs b/tests/expectations/tests/dynamic_loading_attributes.rs
new file mode 100644
index 00000000..b50fbd08
--- /dev/null
+++ b/tests/expectations/tests/dynamic_loading_attributes.rs
@@ -0,0 +1,56 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+extern crate libloading;
+pub struct TestLib {
+ __library: ::libloading::Library,
+ pub foo: unsafe extern "C" fn(
+ x: ::std::os::raw::c_int,
+ y: ::std::os::raw::c_int,
+ ) -> ::std::os::raw::c_int,
+ pub baz: unsafe extern "C" fn() -> ::std::os::raw::c_int,
+}
+impl TestLib {
+ pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
+ where
+ P: AsRef<::std::ffi::OsStr>,
+ {
+ let library = ::libloading::Library::new(path)?;
+ Self::from_library(library)
+ }
+ pub unsafe fn from_library<L>(
+ library: L,
+ ) -> Result<Self, ::libloading::Error>
+ where
+ L: Into<::libloading::Library>,
+ {
+ let __library = library.into();
+ let foo = __library.get(b"foo\0").map(|sym| *sym)?;
+ let baz = __library.get(b"baz\0").map(|sym| *sym)?;
+ Ok(TestLib {
+ __library,
+ foo,
+ baz,
+ })
+ }
+ #[must_use]
+ #[doc = " @brief A function"]
+ #[doc = ""]
+ #[doc = " @param x"]
+ #[doc = " @param y"]
+ #[doc = " @return int"]
+ pub unsafe fn foo(
+ &self,
+ x: ::std::os::raw::c_int,
+ y: ::std::os::raw::c_int,
+ ) -> ::std::os::raw::c_int {
+ (self.foo)(x, y)
+ }
+ pub unsafe fn baz(&self) -> ::std::os::raw::c_int {
+ (self.baz)()
+ }
+}
diff --git a/tests/headers/dynamic_loading_attributes.h b/tests/headers/dynamic_loading_attributes.h
new file mode 100644
index 00000000..e2ca62b1
--- /dev/null
+++ b/tests/headers/dynamic_loading_attributes.h
@@ -0,0 +1,11 @@
+// bindgen-flags: --dynamic-loading TestLib --dynamic-link-require-all --enable-function-attribute-detection
+/**
+ * @brief A function
+ *
+ * @param x
+ * @param y
+ * @return int
+ */
+__attribute__((warn_unused_result))
+int foo(int x, int y);
+int baz() ;