diff --git a/lib/ClangImporter/MappedTypes.def b/lib/ClangImporter/MappedTypes.def index ea4610eb0e2..ca7b63a7012 100644 --- a/lib/ClangImporter/MappedTypes.def +++ b/lib/ClangImporter/MappedTypes.def @@ -129,6 +129,9 @@ MAP_STDLIB_TYPE("u_int64_t", UnsignedInt, 64, "UInt64", false, DoNothing) MAP_STDLIB_TYPE("va_list", VaList, 0, "CVaListPointer", false, DoNothing) MAP_STDLIB_TYPE("__gnuc_va_list", VaList, 0, "CVaListPointer", false, DoNothing) MAP_STDLIB_TYPE("__va_list", VaList, 0, "CVaListPointer", false, DoNothing) +// Cover all va_list family of types just aliased by __builtin_va_list, including +// __isoc_va_list from wasi-libc. +MAP_STDLIB_TYPE("__builtin_va_list", VaList, 0, "CVaListPointer", false, DoNothing) // libkern/OSTypes.h types. MAP_STDLIB_TYPE("UInt", UnsignedInt, 32, "CUnsignedInt", false, DoNothing) diff --git a/test/ClangImporter/Inputs/custom-modules/CVarArgs.h b/test/ClangImporter/Inputs/custom-modules/CVarArgs.h new file mode 100644 index 00000000000..53fd7057a11 --- /dev/null +++ b/test/ClangImporter/Inputs/custom-modules/CVarArgs.h @@ -0,0 +1,7 @@ +#include +extern void takeVaList(va_list args); + +extern void takeVaList2(__builtin_va_list args); + +typedef __builtin_va_list my_builtin_va_list_alias; +extern void takeVaList3(my_builtin_va_list_alias args); diff --git a/test/ClangImporter/Inputs/custom-modules/module.modulemap b/test/ClangImporter/Inputs/custom-modules/module.modulemap index 89ccced682b..b37985ec675 100644 --- a/test/ClangImporter/Inputs/custom-modules/module.modulemap +++ b/test/ClangImporter/Inputs/custom-modules/module.modulemap @@ -283,3 +283,8 @@ module Aliases { module RetroactiveVersioning { header "versioning.h" } + +module CVarArgs { + header "CVarArgs.h" + export * +} diff --git a/test/ClangImporter/ctypes_valist_wasm.swift b/test/ClangImporter/ctypes_valist_wasm.swift new file mode 100644 index 00000000000..5ec2856f853 --- /dev/null +++ b/test/ClangImporter/ctypes_valist_wasm.swift @@ -0,0 +1,18 @@ +// RUN: %swift-frontend -target wasm32-unknown-wasip1 -parse-stdlib -module-name Swift -I %S/Inputs/custom-modules -typecheck %s + +// REQUIRES: CODEGENERATOR=WebAssembly + +import CVarArgs + +/// ===== Minimal stdlib definitions ===== +typealias Void = () +struct CVaListPointer {} +// Optional definition is required for isOptional check in ClangImporter +enum Optional {} +/// ====================================== + +func testVaList() { + let _: (CVaListPointer) -> Void = CVarArgs.takeVaList + let _: (CVaListPointer) -> Void = CVarArgs.takeVaList2 + let _: (CVaListPointer) -> Void = CVarArgs.takeVaList3 +} diff --git a/test/stdlib/VarArgs.swift b/test/stdlib/VarArgs.swift index 68437b90b61..2f429faa88f 100644 --- a/test/stdlib/VarArgs.swift +++ b/test/stdlib/VarArgs.swift @@ -193,6 +193,25 @@ func test_varArgs7() { } test_varArgs7() +func test_varArgs8() { + // Check with vsnprintf as well just in case to make sure it works with C APIs + // imported from actual libc headers. Why checks with vprintf above are not enough? + // ClangImporter respects the vprintf interface re-defined in LibcShims.h but it could + // be slightly different than the one in platform libc on some platforms, including WASI. + // (e.g. wasi-libc defines `int vprintf(const char *__restrict, __isoc_va_list);` where + // `__isoc_va_list` is `typedef __builtin_va_list __isoc_va_list;`, but LibcShims.h aliases + // __builtin_va_list as `va_list`.) + // https://github.com/swiftlang/swift/issues/72398 + let string = withUnsafeTemporaryAllocation(of: CChar.self, capacity: 512) { buffer in + withVaList([CInt(123)]) { args in + _ = vsnprintf(buffer.baseAddress!, buffer.count, "%d", args) + } + return String(cString: buffer.baseAddress!) + } + print(string) + // CHECK: 123 +} +test_varArgs8() // CHECK: done. my_printf("done.")