| // RUN: %empty-directory(%t) |
| // RUN: %target-build-swift %s -o %t/a.out |
| // RUN: %target-codesign %t/a.out |
| // RUN: %target-run %t/a.out | %FileCheck %s |
| // REQUIRES: executable_test |
| |
| // REQUIRES: objc_interop |
| |
| import Foundation |
| #if os(macOS) |
| import AppKit |
| typealias XXColor = NSColor |
| #endif |
| #if os(iOS) || os(tvOS) || os(watchOS) |
| import UIKit |
| typealias XXColor = UIColor |
| #endif |
| |
| |
| // Exercise some common APIs that make use of C pointer arguments. |
| |
| // |
| // Typed C pointers |
| // |
| |
| let rgb = CGColorSpaceCreateDeviceRGB() |
| let cgRed = CGColor(colorSpace: rgb, components: [1.0, 0.0, 0.0, 1.0])! |
| |
| let nsRed = XXColor(cgColor: cgRed) |
| |
| var r: CGFloat = 0.5, g: CGFloat = 0.5, b: CGFloat = 0.5, a: CGFloat = 0.5 |
| #if os(macOS) |
| nsRed!.getRed(&r, green: &g, blue: &b, alpha: &a) |
| #else |
| nsRed.getRed(&r, green: &g, blue: &b, alpha: &a) |
| #endif |
| |
| // CHECK-LABEL: Red is: |
| print("Red is:") |
| print("<\(r) \(g) \(b) \(a)>") // CHECK-NEXT: <1.0 0.0 0.0 1.0> |
| |
| // |
| // Void C pointers |
| // |
| |
| // FIXME: Array type annotation should not be required |
| let data = NSData(bytes: [1.5, 2.25, 3.125] as [Double], |
| length: MemoryLayout<Double>.size * 3) |
| var fromData = [0.25, 0.25, 0.25] |
| let notFromData = fromData |
| data.getBytes(&fromData, length: MemoryLayout<Double>.size * 3) |
| |
| // CHECK-LABEL: Data is: |
| print("Data is:") |
| print(fromData[0]) // CHECK-NEXT: 1.5 |
| print(fromData[1]) // CHECK-NEXT: 2.25 |
| print(fromData[2]) // CHECK-NEXT: 3.125 |
| |
| // CHECK-LABEL: Independent data is: |
| print("Independent data is:") |
| print(notFromData[0]) // CHECK-NEXT: 0.25 |
| print(notFromData[1]) // CHECK-NEXT: 0.25 |
| print(notFromData[2]) // CHECK-NEXT: 0.25 |
| |
| // |
| // ObjC pointers |
| // |
| |
| class Canary: NSObject { |
| deinit { |
| print("died") |
| } |
| } |
| |
| var CanaryAssocObjectHandle: UInt8 = 0 |
| |
| // Attach an associated object with a loud deinit so we can see that the |
| // error died. |
| func hangCanary(_ o: AnyObject) { |
| objc_setAssociatedObject(o, &CanaryAssocObjectHandle, Canary(), |
| .OBJC_ASSOCIATION_RETAIN_NONATOMIC) |
| } |
| |
| // CHECK-LABEL: NSError out: |
| print("NSError out:") |
| autoreleasepool { |
| do { |
| let s = try NSString(contentsOfFile: "/hopefully/does/not/exist\u{1B}", |
| encoding: String.Encoding.utf8.rawValue) |
| _preconditionFailure("file should not actually exist") |
| } catch { |
| print(error._code) // CHECK-NEXT: 260 |
| hangCanary(error as NSError) |
| } |
| } |
| // The result error should have died with the autorelease pool |
| // CHECK-NEXT: died |
| class DumbString: NSString { |
| override func character(at x: Int) -> unichar { _preconditionFailure("nope") } |
| override var length: Int { return 0 } |
| |
| convenience init(contentsOfFile s: String, encoding: String.Encoding) throws { |
| self.init() |
| throw NSError(domain: "Malicious Mischief", code: 594, userInfo: nil) |
| } |
| } |
| |
| // CHECK-LABEL: NSError in: |
| print("NSError in:") |
| autoreleasepool { |
| do { |
| try DumbString(contentsOfFile: "foo", encoding: .utf8) |
| } catch { |
| print(error._domain) // CHECK-NEXT: Malicious Mischief |
| print(error._code) // CHECK-NEXT: 594 |
| hangCanary(error as NSError) |
| } |
| } |
| // The result error should have died with the autorelease pool |
| // CHECK-NEXT: died |
| |
| let s = "Hello World" |
| puts(s) |
| // CHECK-NEXT: Hello World |
| |
| // |
| // C function pointers |
| // |
| |
| var unsorted = [3, 14, 15, 9, 2, 6, 5] |
| qsort(&unsorted, unsorted.count, MemoryLayout.size(ofValue: unsorted[0])) { a, b in |
| return Int32(a!.load(as: Int.self) - b!.load(as: Int.self)) |
| } |
| // CHECK-NEXT: [2, 3, 5, 6, 9, 14, 15] |
| print(unsorted) |