Repository: mozilla/cbindgen (language: rust)

Issue:
Support variadic arguments (`args: ...` syntax)
There are [many cases in Relibc](https://gitlab.redox-os.org/search?utf8=%E2%9C%93&search=%2F%2F+TODO%3A+Can+be+implemented+in+rust+when+cbindgen+supports+%22...%22+syntax&group_id=&project_id=64&search_code=true&repository_ref=master) where Rust functions are wrapped in C functions only to make them use `...` syntax.

Related Rust RFC: https://github.com/rust-lang/rfcs/blob/master/text/2137-variadic.md


Discussion / hints:
This shouldn't be hard to implement, if you want to give it a shot I'm happy to mentor :)
How to implement?
Given this code:

```rust
#[no_mangle]
pub unsafe extern "C" fn func(fixed: u32, mut args: ...) {
    let x: u8 = args.arg();
    let y: u16 = args.arg();
    let z: u32 = args.arg();
    println!("{} {} {} {}", fixed, x, y, z);
}
```

Right now cbindgen says:

```
ERROR: Cannot use fn t::func (Unsupported type: Verbatim(TokenStream [Punct { op: '.', spacing: Joint }, Punct { op: '.', spacing: Joint }, Punct { op: '.', spacing: Alone }]))
```

So basically the code in `Function::load` that parses the signature needs to be taught about that pattern, and flag the function as variadic rather than treating it as an argument. Then use that flag to generate the appropriate C/C++ code.
> Given this code:
> 
> ```rust
> #[no_mangle]
> pub unsafe extern "C" fn func(fixed: u32, mut args: ...) {
>     let x: u8 = args.arg();
>     let y: u16 = args.arg();
>     let z: u32 = args.arg();
>     println!("{} {} {} {}", fixed, x, y, z);
> }
> ```
> 
> Right now cbindgen says:
> 
> ```
> ERROR: Cannot use fn t::func (Unsupported type: Verbatim(TokenStream [Punct { op: '.', spacing: Joint }, Punct { op: '.', spacing: Joint }, Punct { op: '.', spacing: Alone }]))
> ```
> 
> So basically the code in `Function::load` that parses the signature needs to be taught about that pattern, and flag the function as variadic rather than treating it as an argument. Then use that flag to generate the appropriate C/C++ code.

can you fix it?
I mean, I could, but I have no real incentive to right now and cbindgen is just a free-time kinda thing. So I'd rather let other people help with the project and get introduced to it, specially since this is not particularly super-complicated.
> Unsupported type:

Why say this? I create a testcase and it's do nothing
I know nothing about cbindgen, hard for me to fix it

Fix patch:
diff --git a/src/bindgen/ir/ty.rs b/src/bindgen/ir/ty.rs
index 5c68e4ca1..63938b26d 100644
--- a/src/bindgen/ir/ty.rs
+++ b/src/bindgen/ir/ty.rs
@@ -538,6 +538,9 @@ impl Type {
                 }
                 return Err("Tuples are not supported types.".to_owned());
             }
+            syn::Type::Verbatim(ref tokens) if tokens.to_string() == "..." => {
+                Type::Primitive(PrimitiveType::VaList)
+            }
             _ => return Err(format!("Unsupported type: {:?}", ty)),
         };
 


Test patch:
diff --git a/tests/expectations/va_list.c b/tests/expectations/va_list.c
index 2332c27fa..d2f9ac39e 100644
--- a/tests/expectations/va_list.c
+++ b/tests/expectations/va_list.c
@@ -4,3 +4,5 @@
 #include <stdlib.h>
 
 int32_t va_list_test(va_list ap);
+
+int32_t va_list_test2(va_list ap);
diff --git a/tests/expectations/va_list.compat.c b/tests/expectations/va_list.compat.c
index acaae099e..bdd8f4bbb 100644
--- a/tests/expectations/va_list.compat.c
+++ b/tests/expectations/va_list.compat.c
@@ -9,6 +9,8 @@ extern "C" {
 
 int32_t va_list_test(va_list ap);
 
+int32_t va_list_test2(va_list ap);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/tests/expectations/va_list.cpp b/tests/expectations/va_list.cpp
index 80590743b..2a3344b1a 100644
--- a/tests/expectations/va_list.cpp
+++ b/tests/expectations/va_list.cpp
@@ -8,4 +8,6 @@ extern "C" {
 
 int32_t va_list_test(va_list ap);
 
+int32_t va_list_test2(va_list ap);
+
 } // extern "C"
diff --git a/tests/expectations/va_list.pyx b/tests/expectations/va_list.pyx
index a69280881..4ce0c8d7a 100644
--- a/tests/expectations/va_list.pyx
+++ b/tests/expectations/va_list.pyx
@@ -7,3 +7,5 @@ cdef extern from *:
 cdef extern from *:
 
   int32_t va_list_test(va_list ap);
+
+  int32_t va_list_test2(va_list ap);
diff --git a/tests/rust/va_list.rs b/tests/rust/va_list.rs
index 1016091a9..13503dda7 100644
--- a/tests/rust/va_list.rs
+++ b/tests/rust/va_list.rs
@@ -4,3 +4,8 @@ use std::ffi::VaList;
 pub unsafe extern "C" fn va_list_test(mut ap: VaList) -> int32_t {
     ap.arg()
 }
+
+#[no_mangle]
+pub unsafe extern "C" fn va_list_test2(mut ap: ...) -> int32_t {
+    ap.arg()
+}