diff --git a/CHANGELOG.md b/CHANGELOG.md index aea2e321cc..bbd4f198e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -167,6 +167,8 @@ ## Added ## Changed +* Wrappers for static functions that return `void` no longer contain a `return` + statement and only call the static function instead. ## Removed diff --git a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c index abc5224229..8d6e97aad1 100644 --- a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c +++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c @@ -10,3 +10,4 @@ int takes_fn__extern(int (f) (int)) { return takes_fn(f); } int takes_alias__extern(func f) { return takes_alias(f); } int takes_qualified__extern(const int *const *arg) { return takes_qualified(arg); } enum foo takes_enum__extern(const enum foo f) { return takes_enum(f); } +void nevermore__extern(void) { nevermore(); } diff --git a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs index 0db78054ac..2800d7034d 100644 --- a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs +++ b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs @@ -56,3 +56,7 @@ extern "C" { #[link_name = "takes_enum__extern"] pub fn takes_enum(f: foo) -> foo; } +extern "C" { + #[link_name = "nevermore__extern"] + pub fn nevermore(); +} diff --git a/bindgen-tests/tests/headers/wrap-static-fns.h b/bindgen-tests/tests/headers/wrap-static-fns.h index faa7b7f1ad..4a1862b050 100644 --- a/bindgen-tests/tests/headers/wrap-static-fns.h +++ b/bindgen-tests/tests/headers/wrap-static-fns.h @@ -40,3 +40,7 @@ enum foo { static inline enum foo takes_enum(const enum foo f) { return f; } + +static inline void nevermore() { + while (1) { } +} diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs index ac6202356e..0baa70a899 100644 --- a/bindgen/codegen/serialize.rs +++ b/bindgen/codegen/serialize.rs @@ -102,14 +102,31 @@ impl<'a> CSerialize<'a> for Function { // The name used for the wrapper self. let wrap_name = format!("{}{}", name, ctx.wrap_static_fns_suffix()); + // The function's return type - let ret_ty = signature.return_type(); + let ret_ty = { + let type_id = signature.return_type(); + let item = ctx.resolve_item(type_id); + let ret_ty = item.expect_type(); + + // Write `ret_ty`. + ret_ty.serialize(ctx, item, stack, writer)?; + + ret_ty + }; - // Write `ret_ty wrap_name(args) { return name(arg_names)' }` - ret_ty.serialize(ctx, (), stack, writer)?; + // Write `wrap_name(args`. write!(writer, " {}(", wrap_name)?; serialize_args(&args, ctx, writer)?; - write!(writer, ") {{ return {}(", name)?; + + // Write `) { name(` if the function returns void and `) { return name(` if it does not. + if ret_ty.is_void() { + write!(writer, ") {{ {}(", name)?; + } else { + write!(writer, ") {{ return {}(", name)?; + } + + // Write `arg_names); }`. serialize_sep(", ", args.iter(), ctx, writer, |(name, _), _, buf| { write!(buf, "{}", name).map_err(From::from) })?; diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs index 8c505aa49f..572d7de451 100644 --- a/bindgen/ir/ty.rs +++ b/bindgen/ir/ty.rs @@ -124,6 +124,10 @@ impl Type { matches!(self.kind, TypeKind::Enum(..)) } + /// Is this void? + pub(crate) fn is_void(&self) -> bool { + matches!(self.kind, TypeKind::Void) + } /// Is this either a builtin or named type? pub(crate) fn is_builtin_or_type_param(&self) -> bool { matches!(