diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift index 8576a86568b01..40a134baedaf1 100644 --- a/stdlib/public/core/VarArgs.swift +++ b/stdlib/public/core/VarArgs.swift @@ -63,6 +63,17 @@ protocol _CVarArgAligned: CVarArg { var _cVarArgAlignment: Int { get } } +#if !_runtime(_ObjC) +/// Some pointers require an alternate object to be retained. The object +/// that is returned will be used with _cVarArgEncoding and held until +/// the closure is complete. This is required since autoreleased storage +/// is not available on all platforms. +public protocol _CVarArgObject: CVarArg { + /// Returns the alternate object that should be encoded. + var _cVarArgObject: CVarArg { get } +} +#endif + #if arch(x86_64) @usableFromInline internal let _countGPRegisters = 6 @@ -462,6 +473,11 @@ final internal class __VaListBuilder { @usableFromInline // c-abi internal var storage: ContiguousArray +#if !_runtime(_ObjC) + @usableFromInline // c-abi + internal var retainer = [CVarArg]() +#endif + @inlinable // c-abi internal init() { // prepare the register save area @@ -473,6 +489,16 @@ final internal class __VaListBuilder { @inlinable // c-abi internal func append(_ arg: CVarArg) { +#if !_runtime(_ObjC) + var arg = arg + + // We may need to retain an object that provides a pointer value. + if let obj = arg as? _CVarArgObject { + arg = obj._cVarArgObject + retainer.append(arg) + } +#endif + var encoded = arg._cVarArgEncoding #if arch(x86_64) || arch(arm64) @@ -560,6 +586,16 @@ final internal class __VaListBuilder { @inlinable // c-abi internal func append(_ arg: CVarArg) { +#if !_runtime(_ObjC) + var arg = arg + + // We may need to retain an object that provides a pointer value. + if let obj = arg as? _CVarArgObject { + arg = obj._cVarArgObject + retainer.append(arg) + } +#endif + // Write alignment padding if necessary. // This is needed on architectures where the ABI alignment of some // supported vararg type is greater than the alignment of Int, such @@ -665,6 +701,11 @@ final internal class __VaListBuilder { @usableFromInline // c-abi internal var storage: UnsafeMutablePointer? +#if !_runtime(_ObjC) + @usableFromInline // c-abi + internal var retainer = [CVarArg]() +#endif + internal static var alignedStorageForEmptyVaLists: Double = 0 }