summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs32
-rw-r--r--src/ir/context.rs3
-rw-r--r--tests/expectations/tests/func_return_must_use.rs76
-rw-r--r--tests/headers/func_return_must_use.h36
4 files changed, 142 insertions, 5 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index e4ce9526..fdc9b5ed 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -3965,11 +3965,35 @@ impl CodeGenerator for Function {
let mut attributes = vec![];
- if signature.must_use() &&
- ctx.options().rust_features().must_use_function
- {
- attributes.push(attributes::must_use());
+ if ctx.options().rust_features().must_use_function {
+ let must_use = signature.must_use() || {
+ let ret_ty = signature.return_type();
+
+ let resolved_ret = ret_ty
+ .into_resolver()
+ .through_type_refs()
+ .through_type_aliases()
+ .resolve(ctx);
+
+ let must_use_resolved_ty =
+ resolved_ret.annotations().must_use_type() ||
+ ctx.must_use_type_by_name(resolved_ret);
+
+ let ret = ctx.resolve_item(ret_ty);
+ let must_use_ty = ret.annotations().must_use_type() ||
+ ctx.must_use_type_by_name(ret);
+
+ // If the return type already has #[must_use], the function does not
+ // need the annotation. This preserves the codegen behavior before
+ // type aliases with #[must_use] were supported.
+ !must_use_resolved_ty && must_use_ty
+ };
+
+ if must_use {
+ attributes.push(attributes::must_use());
+ }
}
+
if let Some(comment) = item.comment(ctx) {
attributes.push(attributes::doc(comment));
}
diff --git a/src/ir/context.rs b/src/ir/context.rs
index 9cf43ec3..2f71debd 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -1921,7 +1921,8 @@ If you encounter an error missing from this list, please file an issue or a PR!"
let item = Item::new(
with_id,
None,
- None,
+ self.resolve_item_fallible(wrapped_id)
+ .map(|item| item.annotations().clone()),
parent_id.unwrap_or_else(|| self.current_module.into()),
ItemKind::Type(ty),
Some(location),
diff --git a/tests/expectations/tests/func_return_must_use.rs b/tests/expectations/tests/func_return_must_use.rs
new file mode 100644
index 00000000..9f40aaa6
--- /dev/null
+++ b/tests/expectations/tests/func_return_must_use.rs
@@ -0,0 +1,76 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+pub type MustUseInt = ::std::os::raw::c_int;
+extern "C" {
+ #[must_use]
+ pub fn return_int() -> MustUseInt;
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+#[must_use]
+pub struct MustUseStruct {
+ _unused: [u8; 0],
+}
+extern "C" {
+ pub fn return_struct() -> MustUseStruct;
+}
+/// <div rustbindgen mustusetype></div>
+pub type AnnotatedInt = ::std::os::raw::c_int;
+extern "C" {
+ #[must_use]
+ pub fn return_annotated_int() -> AnnotatedInt;
+}
+extern "C" {
+ pub fn return_plain_int() -> ::std::os::raw::c_int;
+}
+/// <div rustbindgen mustusetype></div>
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+#[must_use]
+pub struct AnnotatedStruct {}
+#[test]
+fn bindgen_test_layout_AnnotatedStruct() {
+ assert_eq!(
+ ::std::mem::size_of::<AnnotatedStruct>(),
+ 0usize,
+ concat!("Size of: ", stringify!(AnnotatedStruct))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<AnnotatedStruct>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(AnnotatedStruct))
+ );
+}
+extern "C" {
+ pub fn return_annotated_struct() -> AnnotatedStruct;
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct PlainStruct {}
+#[test]
+fn bindgen_test_layout_PlainStruct() {
+ assert_eq!(
+ ::std::mem::size_of::<PlainStruct>(),
+ 0usize,
+ concat!("Size of: ", stringify!(PlainStruct))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<PlainStruct>(),
+ 1usize,
+ concat!("Alignment of ", stringify!(PlainStruct))
+ );
+}
+/// <div rustbindgen mustusetype></div>
+pub type TypedefPlainStruct = PlainStruct;
+extern "C" {
+ pub fn return_plain_struct() -> PlainStruct;
+}
+extern "C" {
+ #[must_use]
+ pub fn return_typedef_struct() -> TypedefPlainStruct;
+}
diff --git a/tests/headers/func_return_must_use.h b/tests/headers/func_return_must_use.h
new file mode 100644
index 00000000..f05bd2de
--- /dev/null
+++ b/tests/headers/func_return_must_use.h
@@ -0,0 +1,36 @@
+// bindgen-flags: --must-use-type 'MustUse.*'
+
+typedef int MustUseInt;
+
+MustUseInt return_int();
+
+struct MustUseStruct;
+
+struct MustUseStruct return_struct();
+
+/**
+ * <div rustbindgen mustusetype></div>
+ */
+typedef int AnnotatedInt;
+
+AnnotatedInt return_annotated_int();
+
+int return_plain_int();
+
+/**
+ * <div rustbindgen mustusetype></div>
+ */
+struct AnnotatedStruct {};
+
+struct AnnotatedStruct return_annotated_struct();
+
+struct PlainStruct {};
+
+/**
+ * <div rustbindgen mustusetype></div>
+ */
+typedef struct PlainStruct TypedefPlainStruct;
+
+struct PlainStruct return_plain_struct();
+
+TypedefPlainStruct return_typedef_struct();