Skip to content

Commit 8a13baf

Browse files
authored
Work around miscompilation of entry point function on Windows with Swift 5.10. (#381)
This PR works around two apparent miscompiles of the entry point function added with #360. These workarounds are only necessary on Windows when using the Swift 5.10 compiler (I've seen no indication of issues on other platforms or with the Swift 6 compiler.) We can revert this change once we no longer provide any support for the Swift 5.10 toolchain. ### Checklist: - [x] Code and documentation should follow the style of the [Style Guide](https://github.com/apple/swift-testing/blob/main/Documentation/StyleGuide.md). - [x] If public symbols are renamed or modified, DocC references should be updated.
1 parent c5eba93 commit 8a13baf

File tree

4 files changed

+20
-11
lines changed

4 files changed

+20
-11
lines changed

Sources/Testing/EntryPoints/ABIEntryPoint.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ public typealias ABIEntryPoint_v0 = @Sendable (
6060
@usableFromInline
6161
func abiEntryPoint_v0(_ outEntryPoint: UnsafeMutableRawPointer) {
6262
outEntryPoint.initializeMemory(as: ABIEntryPoint_v0.self) { argumentsJSON, eventHandler in
63-
let args = try! argumentsJSON.map { argumentsJSON in
63+
var args = try! argumentsJSON.map { argumentsJSON in
6464
try JSON.decode(__CommandLineArguments_v0.self, from: argumentsJSON)
6565
}
6666

6767
let eventHandler = eventHandlerForStreamingEvents_v0(to: eventHandler)
68-
return await entryPoint(passing: args, eventHandler: eventHandler)
68+
return await entryPoint(passing: &args, eventHandler: eventHandler)
6969
}
7070
}
7171
#endif

Sources/Testing/EntryPoints/EntryPoint.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ private import TestingInternals
2626
/// - Warning: This function is used by Swift Package Manager. Do not call it
2727
/// directly.
2828
@_disfavoredOverload public func __swiftPMEntryPoint(passing args: __CommandLineArguments_v0? = nil) async -> CInt {
29-
await entryPoint(passing: args, eventHandler: nil)
29+
var args = args
30+
return await entryPoint(passing: &args, eventHandler: nil)
3031
}
3132

3233
/// The entry point to the testing library used by Swift Package Manager.
@@ -55,12 +56,17 @@ public func __swiftPMEntryPoint(passing args: __CommandLineArguments_v0? = nil)
5556
/// - args: A previously-parsed command-line arguments structure to interpret.
5657
/// If `nil`, a new instance is created from the command-line arguments to
5758
/// the current process.
58-
/// - eventHandler: An event handler
59-
func entryPoint(passing args: __CommandLineArguments_v0?, eventHandler: Event.Handler?) async -> CInt {
59+
/// - eventHandler: An event handler.
60+
///
61+
/// - Bug: This function takes `args` as a pointer in order to work around a
62+
/// code generation bug when using the Swift 5.10 toolchain on Windows. This
63+
/// function should be updated to take `args` directly when Swift 5.10
64+
/// support is removed.
65+
func entryPoint(passing args: UnsafePointer<__CommandLineArguments_v0?>, eventHandler: Event.Handler?) async -> CInt {
6066
let exitCode = Locked(rawValue: EXIT_SUCCESS)
6167

6268
do {
63-
let args = try args ?? parseCommandLineArguments(from: CommandLine.arguments())
69+
let args = try args.pointee ?? parseCommandLineArguments(from: CommandLine.arguments())
6470
if args.listTests {
6571
for testID in await listTestsForSwiftPM(Test.all) {
6672
#if SWT_TARGET_OS_APPLE && !SWT_NO_FILE_IO

Sources/Testing/EntryPoints/XCTestScaffold.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ public enum XCTestScaffold: Sendable {
144144
functionName[...]
145145
}
146146
args.xcTestCaseHostIdentifier = "\(typeName)/\(functionName)"
147+
var argsCopy: __CommandLineArguments_v0? = args
147148

148-
_ = await entryPoint(passing: args) { event, _ in
149+
_ = await entryPoint(passing: &argsCopy) { event, _ in
149150
guard case let .issueRecorded(issue) = event.kind else {
150151
return
151152
}

Tests/TestingTests/ABIEntryPointTests.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ struct ABIEntryPointTests {
2828
}
2929
)
3030
#endif
31-
let abiEntryPoint = withUnsafeTemporaryAllocation(of: ABIEntryPoint_v0.self, capacity: 1) { buffer in
32-
copyABIEntryPoint(buffer.baseAddress!)
33-
return buffer.baseAddress!.move()
31+
let abiEntryPoint = UnsafeMutablePointer<ABIEntryPoint_v0>.allocate(capacity: 1)
32+
copyABIEntryPoint(abiEntryPoint)
33+
defer {
34+
abiEntryPoint.deinitialize(count: 1)
35+
abiEntryPoint.deallocate()
3436
}
3537

3638
// Construct arguments and convert them to JSON.
@@ -46,7 +48,7 @@ struct ABIEntryPointTests {
4648
}
4749

4850
// Call the entry point function.
49-
let result = await abiEntryPoint(.init(argumentsJSON)) { eventAndContextJSON in
51+
let result = await abiEntryPoint.pointee(.init(argumentsJSON)) { eventAndContextJSON in
5052
let eventAndContext = try! JSON.decode(EventAndContextSnapshot.self, from: eventAndContextJSON)
5153
_ = (eventAndContext.event, eventAndContext.eventContext)
5254
}

0 commit comments

Comments
 (0)