mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Change the syntax of availability queries from #available(iOS >= 8.0, OSX >= 10.10, *) to This change reflects the fact that now that we spell the query '#available()' rather than '#os()', the specification is about availability of the APIs introduced in a particular OS release rather than an explicit range of OS versions on which the developer expects the code to run. There is a Fix-It to remove '>=' to ease adopting the new syntax. Swift SVN r28025
259 lines
6.8 KiB
Plaintext
259 lines
6.8 KiB
Plaintext
//===--- BridgeStorage.swift.gyb ------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Bridged types are notionally single-word beasts that either store
|
|
// an objc class or a native Swift class. We'd like to be able to
|
|
// distinguish these cases efficiently.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
// RUN: rm -rf %t && mkdir -p %t && %S/../../utils/gyb %s -o %t/out.swift
|
|
// RUN: %S/../../utils/line-directive %t/out.swift -- %target-build-swift -parse-stdlib %t/out.swift -o %t/a.out
|
|
// RUN: %S/../../utils/line-directive %t/out.swift -- %target-run %t/a.out
|
|
|
|
// REQUIRES: objc_interop
|
|
|
|
import Swift
|
|
|
|
//===--- Code destined for stdlib -----------------------------------------===//
|
|
import SwiftShims
|
|
|
|
protocol BridgeStorage {
|
|
typealias Native : AnyObject
|
|
typealias ObjC : AnyObject
|
|
|
|
init(native: Native, bits: Int)
|
|
init(native: Native)
|
|
init(objC: ObjC)
|
|
|
|
mutating func isUniquelyReferencedNative() -> Bool
|
|
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool
|
|
var isNative: Bool {get}
|
|
var isObjC: Bool {get}
|
|
var nativeInstance: Native {get}
|
|
var nativeInstance_noSpareBits: Native {get}
|
|
var objCInstance: ObjC {get}
|
|
var spareBits: Int {get}
|
|
}
|
|
|
|
extension _BridgeStorage : BridgeStorage {}
|
|
|
|
|
|
struct BridgeObject<NativeType : AnyObject, ObjCType : AnyObject>
|
|
: BridgeStorage {
|
|
|
|
typealias Native = NativeType
|
|
typealias ObjC = ObjCType
|
|
|
|
init(native: Native, bits: Int) {
|
|
_sanityCheck(
|
|
bits >= 0 && bits < 2,
|
|
"BridgeObject can't store bits outside the range 0-1")
|
|
|
|
self.object = native
|
|
self.bits = UInt8(truncatingBitPattern: bits)
|
|
}
|
|
|
|
init(native: Native) {
|
|
self.object = native
|
|
self.bits = 0
|
|
}
|
|
|
|
init(objC: ObjC) {
|
|
self.object = objC
|
|
self.bits = 0
|
|
}
|
|
|
|
mutating func isUniquelyReferencedNative() -> Bool {
|
|
return _swift_isUniquelyReferencedNonObjC_nonNull(
|
|
UnsafePointer(rawObject))
|
|
}
|
|
|
|
var isNative: Bool {
|
|
return _swift_usesNativeSwiftReferenceCounting_nonNull(
|
|
UnsafePointer(rawObject))
|
|
}
|
|
|
|
var isObjC: Bool {
|
|
return !isNative
|
|
}
|
|
|
|
var nativeInstance: Native {
|
|
precondition(isNative)
|
|
return Builtin.bridgeFromRawPointer(rawObject)
|
|
}
|
|
|
|
var nativeInstance_noSpareBits: Native {
|
|
precondition(isNative)
|
|
precondition(spareBits == 0)
|
|
return Builtin.bridgeFromRawPointer(rawObject)
|
|
}
|
|
|
|
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool {
|
|
precondition(isNative)
|
|
precondition(spareBits == 0)
|
|
return _swift_isUniquelyReferenced_nonNull_native(
|
|
UnsafePointer(rawObject))
|
|
}
|
|
|
|
var objCInstance: ObjC {
|
|
precondition(isObjC)
|
|
return Builtin.bridgeFromRawPointer(rawObject)
|
|
}
|
|
|
|
var spareBits: Int {
|
|
return Int(bits)
|
|
}
|
|
|
|
var rawObject: Builtin.RawPointer {
|
|
return Builtin.bridgeToRawPointer(object)
|
|
}
|
|
|
|
let object: AnyObject
|
|
let bits: UInt8
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
//===--- Testing code -----------------------------------------------------===//
|
|
//===----------------------------------------------------------------------===//
|
|
import StdlibUnittest
|
|
var allTests = TestSuite("DiscriminatedBridgeObject")
|
|
|
|
class C {
|
|
deinit {
|
|
println("bye C!")
|
|
}
|
|
}
|
|
import Foundation
|
|
|
|
func isOSAtLeast(major: Int, _ minor: Int, patch: Int = 0) -> Bool {
|
|
let vers = (majorVersion: major, minorVersion: minor, patchVersion: patch)
|
|
// isOperatingSystemAtLeastVersion() is unavailable on some OS versions.
|
|
if #available(iOS 8.0, OSX 10.10, *) {
|
|
let procInfo: AnyObject = NSProcessInfo.processInfo()
|
|
return procInfo.isOperatingSystemAtLeastVersion(
|
|
NSOperatingSystemVersion(vers)
|
|
)
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func expectTagged(s: NSString, _ expected: Bool) -> NSString {
|
|
#if arch(x86_64)
|
|
let mask: UWord = 0x8000000000000001
|
|
#elseif arch(arm64)
|
|
let mask: UWord = 0x8000000000000000
|
|
#else
|
|
let mask: UWord = 0
|
|
#endif
|
|
|
|
var osSupportsTaggedStrings: Bool
|
|
#if os(iOS)
|
|
// NSTaggedPointerString is enabled starting in iOS 9.0.
|
|
osSupportsTaggedStrings = isOSAtLeast(9,0)
|
|
#elseif os(tvOS)
|
|
// NSTaggedPointerString is supported in all versions of TVOS.
|
|
osSupportsTaggedStrings = true
|
|
#elseif os(OSX)
|
|
// NSTaggedPointerString is enabled starting in OS X 10.10.
|
|
osSupportsTaggedStrings = isOSAtLeast(10,10)
|
|
#endif
|
|
|
|
let taggedStringsSupported = osSupportsTaggedStrings && mask != 0
|
|
|
|
let tagged = unsafeBitCast(s, UWord.self) & mask != 0
|
|
|
|
if taggedStringsSupported && expected == tagged {
|
|
// okay
|
|
} else if !taggedStringsSupported && !tagged {
|
|
// okay
|
|
} else {
|
|
let un = !tagged ? "un" : ""
|
|
fatalError("Unexpectedly \(un)tagged pointer for string \"\(s)\"")
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
var taggedNSString : NSString {
|
|
return expectTagged(NSString(format: "foo"), true)
|
|
}
|
|
|
|
var unTaggedNSString : NSString {
|
|
return expectTagged("fûtbōl" as NSString, false)
|
|
}
|
|
|
|
% for Self in '_BridgeStorage', 'BridgeObject':
|
|
allTests.test("${Self}") {
|
|
typealias B = ${Self}<C,NSString>
|
|
|
|
let oy: NSString = "oy"
|
|
expectTrue(B(objC: oy).objCInstance == oy)
|
|
|
|
for i in 0..<2 {
|
|
if true {
|
|
var b = B(native: C(), bits: i)
|
|
expectFalse(b.isObjC)
|
|
expectTrue(b.isNative)
|
|
expectTrue(b.isUniquelyReferencedNative())
|
|
if i == 0 {
|
|
expectTrue(b.isUniquelyReferenced_native_noSpareBits())
|
|
}
|
|
expectEqual(i, b.spareBits)
|
|
}
|
|
|
|
if true {
|
|
let c = C()
|
|
var b = B(native: c, bits: i)
|
|
expectFalse(b.isObjC)
|
|
expectTrue(b.isNative)
|
|
expectFalse(b.isUniquelyReferencedNative())
|
|
expectEqual(i, b.spareBits)
|
|
expectTrue(b.nativeInstance === c)
|
|
if i == 0 {
|
|
expectTrue(b.nativeInstance_noSpareBits === c)
|
|
expectFalse(b.isUniquelyReferenced_native_noSpareBits())
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
var b = B(native: C(), bits: 0)
|
|
expectTrue(b.isUniquelyReferencedNative())
|
|
|
|
// Add a reference and verify that it's still native but no longer unique
|
|
var c = b
|
|
expectFalse(b.isUniquelyReferencedNative())
|
|
_fixLifetime(c) // make sure c is not killed early
|
|
|
|
let n = C()
|
|
var bb = B(native: n)
|
|
expectEqual(0, bb.spareBits)
|
|
expectTrue(bb.nativeInstance === n)
|
|
expectTrue(bb.isNative)
|
|
expectFalse(bb.isObjC)
|
|
|
|
var d = B(objC: taggedNSString)
|
|
expectFalse(d.isUniquelyReferencedNative())
|
|
expectFalse(d.isNative)
|
|
expectTrue(d.isObjC)
|
|
|
|
d = B(objC: unTaggedNSString)
|
|
expectFalse(d.isUniquelyReferencedNative())
|
|
expectFalse(d.isNative)
|
|
expectTrue(d.isObjC)
|
|
|
|
}
|
|
% end
|
|
|
|
runAllTests()
|