blob: 8a7f396a83a5c02ec6ab155b13af8a1d3b6d1f8e [file] [log] [blame]
// RUN: %target-run-simple-swift | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: objc_interop
// The Objective-C runtime does not implement the autorelease
// optimization on i386, even in the iOS simulator.
// XFAIL: CPU=i386
import Foundation
class PrintOnDeinit: NSObject {
// Result should get autoreleased.
@objc dynamic class func create() -> PrintOnDeinit {
return PrintOnDeinit()
}
deinit { print("object died") }
}
func useTemp() {
let f = PrintOnDeinit.create()
}
// objc_retainAutoreleasedReturnValue will fail to reclaim the first
// object autoreleased from each shared object on x86_64, so prime it.
autoreleasepool { useTemp() }
autoreleasepool {
print("autorelease test begin")
useTemp()
print("after call to useTemp")
}
print("autorelease test end")
// CHECK: autorelease test begin
// CHECK-NEXT: object died
// CHECK-NEXT: after call to useTemp
// CHECK-NEXT: autorelease test end
// Using an @objc class to check that errors are retained across the pool
// boundaries. A classic crash is an error created inside a pool and then
// zombied before handling it outside the pool.
@objc class MyError : NSObject, Error {
let message: String
init(message: String) {
self.message = message
}
}
// Check that rethrow works.
func requireString(string: String?) throws -> String {
guard let string = string else {
throw MyError(message: "no string")
}
print("returning \"\(string)\"")
return string
}
do {
try autoreleasepool {
try requireString(string: "ok")
try requireString(string: nil)
}
} catch let err as MyError {
print("caught \"\(err.message)\"")
}
// CHECK-NEXT: returning "ok"
// CHECK-NEXT: caught "no string"
// Check that a return value can be passed back.
let result = try autoreleasepool {
return "a string"
}
print("result = \"\(result)\"")
// CHECK-NEXT: result = "a string"