Files
Odin/core/c/libc/stdarg.odin
T
BBandClaude Opus 5.5 baca00868b Pass va_list by value to libc's v* functions
C passes a va_list argument by value. The bindings took ^va_list, which
only matches x86-64 System V, where va_list is an array that decays to
a pointer. On Darwin, Windows and the other targets va_list is a
pointer or a struct, so vsnprintf and friends received the address of
the list instead of the list and printed or scanned garbage.

The foreign declarations now use the platform's form, and the public
procedures keep taking ^va_list so callers stay portable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 22:10:02 +02:00

37 lines
1.1 KiB
Odin

package libc
// 7.16 Variable arguments
import "base:intrinsics"
va_list :: intrinsics.c_va_list
va_start :: intrinsics.c_va_start
va_end :: intrinsics.c_va_end
va_copy :: intrinsics.c_va_copy
// C passes a va_list by value. On x86-64 System V it is an array, which decays to a pointer
// to its first element; everywhere else the value itself is passed.
when ODIN_ARCH == .amd64 && ODIN_OS != .Windows {
@(private) va_list_arg :: ^va_list
} else {
@(private) va_list_arg :: va_list
}
// The va_list argument for a C function, from the pointer the v* procedures here take.
@(private)
va_list_arg_from :: #force_inline proc "contextless" (arg: ^va_list) -> va_list_arg {
when ODIN_ARCH == .amd64 && ODIN_OS != .Windows {
return arg
} else {
return arg^
}
}
// We cannot provide va_arg as there is no way to create "C" style procedures
// in Odin which take variable arguments the C way. The #c_vararg attribute only
// exists for foreign imports. That being said, being able to copy a va_list,
// as well as start and end one is necessary in some functions, the va_list
// taking functions in libc as an example.