Skip to content

add c-variadic function definitions#2177

Open
folkertdev wants to merge 2 commits intorust-lang:masterfrom
folkertdev:c-variadic
Open

add c-variadic function definitions#2177
folkertdev wants to merge 2 commits intorust-lang:masterfrom
folkertdev:c-variadic

Conversation

@folkertdev
Copy link
Contributor

I think this has all of the raw material, but needs polishing.

Here is a draft of the stabilization report, for additional context: https://hackmd.io/@Q66MPiW4T7yNTKOCaEb-Lw/S1iI3WIwZg

@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label Feb 17, 2026
## C-variadic functions

r[items.fn.c-variadic.intro]
A *c-variadic* function accepts a variable argument list `pat: ...` as its final parameter.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for c-variadic definitions only pat: ... is accepted semantically.

plain ... is currently parsed, the varargs_without_pattern lint is meant to eventually disallow it. This syntax can only be used as an input to macros, when a bare ... makes it past macro expansion, that will emit an error.

I didn't mention this here, but maybe we should: we follow C23 in that pat: ... may be the only argument. Earlier versions of C required at least one standard argument before the ....

Comment on lines +347 to +348
> [!WARNING]
> Passing an unexpected number of arguments or arguments of unexpected type to a variadic function may lead to [undefined behavior][undefined].
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copied from

https://doc.rust-lang.org/reference/items/external-blocks.html?highlight=variadic#r-items.extern.variadic

basically, the responsibility for passing valid arguments is on the caller.

Comment on lines +369 to +377
unsafe extern "C" fn example() -> i32 {
let mut storage = MaybeUninit::<VaList<'_>>::uninit();
va_start(storage.as_mut_ptr()); // Initializes the VaList.
let mut ap: &mut VaList<'_> = ap.assume_init_mut();

unsafe { ap.arg::<i32>() }

va_end(ap)
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

va_start and va_end are C functions/concepts. We could instead handwave and say

let mut ap: VaList<'_> = /* ... */; // Initializes the VaList.

the va_end is called by the VaList Drop implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: The marked PR is awaiting review from a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments