Repository: rust-lang/rust-bindgen (rust)

Issue:
wrapper void (*name)(void)or const void * const stack cause problem
I try to use  --wrap-static-fns to wrap static inline function in Rust for Linux ,the wrapped .c file have problem to gengrate .o file 

### Input C/C++ Header

```C++
static inline void __list_splice_init_rcu(struct list_head *list,
					  struct list_head *prev,
					  struct list_head *next,
					  void (*sync)(void))
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

	INIT_LIST_HEAD_RCU(list);

	sync();
	ASSERT_EXCLUSIVE_ACCESS(*first);
	ASSERT_EXCLUSIVE_ACCESS(*last);

	last->next = next;
	rcu_assign_pointer(list_next_rcu(prev), first);
	first->prev = prev;
	next->prev = last;
}
```

### Bindgen Invocation
Rust for Linux generation adds the following options

```
--experimental --wrap-static-fns
```


### Actual Results

```C++
void __list_splice_init_rcu__extern(struct list_head *list, struct list_head *prev, struct list_head *next, void (*sync) ()) 
{ 
	return __list_splice_init_rcu(list, prev, next, sync); 
}
```

when generate .o file from wrapped .c file 

```rust
rust/extern.c:2067:122: error: a function declaration without a prototype is deprecated in all versions of C [-Werror,-Wstrict-prototypes]
void __list_splice_init_rcu__extern(struct list_head *list, struct list_head *prev, struct list_head *next, void (*sync) ()) { return __list_splice_init_rcu(list, prev, next, sync); }
```

Need to manually add void like

```C++
void __list_splice_init_rcu__extern(struct list_head *list, struct list_head *prev, struct list_head *next, void (*sync) (void)) 
{ 
	return __list_splice_init_rcu(list, prev, next, sync); 
}

```

and cause warning 
### Input C/C++ Header

```C++
static inline int arch_within_stack_frames(const void * const stack,
					   const void * const stackend,
					   const void *obj, unsigned long len)
{
#if defined(CONFIG_FRAME_POINTER)
	const void *frame = NULL;
	const void *oldframe;

	oldframe = __builtin_frame_address(1);
	if (oldframe)
		frame = __builtin_frame_address(2);

	while (stack <= frame && frame < stackend) {
		if (obj + len <= frame)
			return obj >= oldframe + 2 * sizeof(void *) ?
				GOOD_FRAME : BAD_STACK;
		oldframe = frame;
		frame = *(const void * const *)frame;
	}
	return BAD_STACK;
#else
	return NOT_STACK;
#endif
}
```

### Actual Results

```C++
int arch_within_stack_frames__extern(const const void *const stack, const const void *const stackend, const void *obj, unsigned long len) 
{ 
	return arch_within_stack_frames(stack, stackend, obj, len); 
}

```

when generate .o file from wrapped .c file ,warning at 
```
const const void *const stack, const const void *const stackend
```

```rust
rust/extern.c:1063:44: warning: duplicate 'const' declaration specifier [-Wduplicate-decl-specifier]
int arch_within_stack_frames__extern(const const void *const stack, const const void *const stackend, const void *obj, unsigned long len) { return arch_within_stack_frames(stack, stackend, obj, len); }

```

### Expected Results
Understand that only supports a very limited set of C functions,expect improvement of static inline function binding.

Pull request:
Use void in parameterless functions
Fixes #2616


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa5af685..9b536800 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -179,6 +179,8 @@
 
 ## Added
 ## Changed
+- The `--wrap-static-fns` feature was updated so function types that has no
+  argument use `void` as its sole argument.
 ## Removed
 ## Fixed
 ## Security
diff --git a/Cargo.toml b/Cargo.toml
index 0c581d66..370828da 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,12 @@ tag-name = "v{{version}}"
 # Don't release any crate unless its manifest has `release = true`
 release = false
 
+# Add version and date to changelog file
+[[workspace.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = "# Unreleased"
+replace = "# {{version}} ({{date}})"
+
 # The profile that 'cargo dist' will build with
 [profile.dist]
 inherits = "release"
diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs
index 58e0882f..02c46802 100644
--- a/bindgen/codegen/serialize.rs
+++ b/bindgen/codegen/serialize.rs
@@ -322,21 +322,26 @@ impl<'a> CSerialize<'a> for Type {
                 }
                 write!(writer, ")")?;
 
-                write!(writer, " (")?;
-                serialize_sep(
-                    ", ",
-                    signature.argument_types().iter(),
-                    ctx,
-                    writer,
-                    |(name, type_id), ctx, buf| {
-                        let mut stack = vec![];
-                        if let Some(name) = name {
-                            stack.push(name.clone());
-                        }
-                        type_id.serialize(ctx, (), &mut stack, buf)
-                    },
-                )?;
-                write!(writer, ")")?
+                let args = signature.argument_types();
+                if args.is_empty() {
+                    write!(writer, " (void)")?;
+                } else {
+                    write!(writer, " (")?;
+                    serialize_sep(
+                        ", ",
+                        args.iter(),
+                        ctx,
+                        writer,
+                        |(name, type_id), ctx, buf| {
+                            let mut stack = vec![];
+                            if let Some(name) = name {
+                                stack.push(name.clone());
+                            }
+                            type_id.serialize(ctx, (), &mut stack, buf)
+                        },
+                    )?;
+                    write!(writer, ")")?
+                }
             }
             TypeKind::ResolvedTypeRef(type_id) => {
                 if self.is_const() {


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 cf1106ec..a8fd5045 100644
--- a/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c
+++ b/bindgen-tests/tests/expectations/tests/generated/wrap_static_fns.c
@@ -11,6 +11,7 @@ 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(); }
+int takes_fn_with_no_args__extern(int (f) (void)) { return takes_fn_with_no_args(f); }
 void no_extra_argument__extern(__builtin_va_list va) { no_extra_argument(va); }
 int many_va_list__extern(int i, __builtin_va_list va1, __builtin_va_list va2) { return many_va_list(i, va1, va2); }
 int wrap_as_variadic_fn1__extern(int i, ...) {
diff --git a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
index 03f3907e..46b369b2 100644
--- a/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
+++ b/bindgen-tests/tests/expectations/tests/wrap-static-fns.rs
@@ -50,6 +50,12 @@ extern "C" {
     #[link_name = "nevermore__extern"]
     pub fn nevermore();
 }
+extern "C" {
+    #[link_name = "takes_fn_with_no_args__extern"]
+    pub fn takes_fn_with_no_args(
+        f: ::std::option::Option<unsafe extern "C" fn() -> ::std::os::raw::c_int>,
+    ) -> ::std::os::raw::c_int;
+}
 extern "C" {
     #[link_name = "no_extra_argument__extern"]
     pub fn no_extra_argument(va: *mut __va_list_tag);
diff --git a/bindgen-tests/tests/headers/wrap-static-fns.h b/bindgen-tests/tests/headers/wrap-static-fns.h
index 8dcabe7b..131b7ab1 100644
--- a/bindgen-tests/tests/headers/wrap-static-fns.h
+++ b/bindgen-tests/tests/headers/wrap-static-fns.h
@@ -52,6 +52,10 @@ static inline void nevermore() {
     while (1) { }
 }
 
+static inline int takes_fn_with_no_args(int(f)(void)) {
+    return f();
+}
+
 static inline int variadic(int x, ...) {
     return x;
 }