Repository: rust-lang/rust-bindgen
Pull request #2416 (2023-02-15 11:05:43)

Also de-duplicate functions with wrapped static functions feature
This PR moves the logic for adding an item to be serialized after all the conditions which defines if a Rust extern function will be created are done. This is to make sure that functions are de-duplicated but also that we don't generate C wrapped that won't be used at all.


Patch:
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs
index b6fb70eb..b5a7b27c 100644
--- a/bindgen/codegen/mod.rs
+++ b/bindgen/codegen/mod.rs
@@ -4029,14 +4029,10 @@ impl CodeGenerator for Function {
 
         let is_internal = matches!(self.linkage(), Linkage::Internal);
 
-        if is_internal {
-            if ctx.options().wrap_static_fns {
-                result.items_to_serialize.push(item.id());
-            } else {
-                // We can't do anything with Internal functions if we are not wrapping them so just
-                // avoid generating anything for them.
-                return None;
-            }
+        if is_internal && !ctx.options().wrap_static_fns {
+            // We can't do anything with Internal functions if we are not wrapping them so just
+            // avoid generating anything for them.
+            return None;
         }
 
         // Pure virtual methods have no actual symbol, so we can't generate
@@ -4139,6 +4135,10 @@ impl CodeGenerator for Function {
             abi => abi,
         };
 
+        if is_internal && ctx.options().wrap_static_fns {
+            result.items_to_serialize.push(item.id());
+        }
+
         // Handle overloaded functions by giving each overload its own unique
         // suffix.
         let times_seen = result.overload_number(&canonical_name);
diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs
index e521c703..13106484 100644
--- a/bindgen/codegen/serialize.rs
+++ b/bindgen/codegen/serialize.rs
@@ -311,6 +311,14 @@ impl<'a> CSerialize<'a> for Type {
                     CompKind::Union => write!(writer, "union {}", name)?,
                 };
             }
+            TypeKind::Enum(_enum_ty) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+
+                let name = item.canonical_name(ctx);
+                write!(writer, "enum {}", name)?;
+            }
             ty => {
                 return Err(CodegenError::Serialize {
                     msg: format!("Cannot serialize type kind {:?}", ty),
diff --git a/book/src/using-bitfields.md b/book/src/using-bitfields.md
index 41e07ad7..0ee9f032 100644
--- a/book/src/using-bitfields.md
+++ b/book/src/using-bitfields.md
@@ -5,7 +5,7 @@
 As Rust does not support bitfields, Bindgen generates a struct for each with the following characteristics
 * Immutable getter functions for each bitfield named ```<bitfield>```
 * Setter functions for each contiguous block of bitfields named ```set_<bitfield>```
-* Far each contiguous block of bitfields, Bindgen emits an opaque physical field that contains one or more logical bitfields
+* For each contiguous block of bitfields, Bindgen emits an opaque physical field that contains one or more logical bitfields
 * A static constructor  ```new_bitfield_{1, 2, ...}``` with a parameter for each bitfield contained within the opaque physical field.
 
 ## Bitfield examples


Test patch:
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 22b2f67f..f5f33f84 100644
--- a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c
+++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c
@@ -12,3 +12,5 @@ int takes_alias__extern(func f) asm("takes_alias__extern");
 int takes_alias__extern(func f) { return takes_alias(f); }
 int takes_qualified__extern(const int *const *arg) asm("takes_qualified__extern");
 int takes_qualified__extern(const int *const *arg) { return takes_qualified(arg); }
+enum foo takes_enum__extern(const enum foo f) asm("takes_enum__extern");
+enum foo takes_enum__extern(const enum foo f) { return takes_enum(f); }
diff --git a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
index 54ed9fd4..fbfdcb13 100644
--- a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
+++ b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
@@ -50,3 +50,9 @@ extern "C" {
         arg: *const *const ::std::os::raw::c_int,
     ) -> ::std::os::raw::c_int;
 }
+pub const foo_BAR: foo = 0;
+pub type foo = ::std::os::raw::c_uint;
+extern "C" {
+    #[link_name = "\u{1}takes_enum__extern"]
+    pub fn takes_enum(f: foo) -> foo;
+}
diff --git a/bindgen-tests/tests/headers/wrap-static-fns.h b/bindgen-tests/tests/headers/wrap-static-fns.h
index 8b90c7bc..faa7b7f1 100644
--- a/bindgen-tests/tests/headers/wrap-static-fns.h
+++ b/bindgen-tests/tests/headers/wrap-static-fns.h
@@ -3,6 +3,7 @@
 static inline int foo() {
     return 11;
 }
+static int bar();
 static int bar() {
     return 1;
 }
@@ -31,3 +32,11 @@ static inline int takes_alias(func f) {
 static inline int takes_qualified(const int *const *arg) {
     return **arg;
 }
+
+enum foo {
+    BAR = 0x0,
+};
+
+static inline enum foo takes_enum(const enum foo f) {
+    return f;
+}