blob: a64e39645ad11e9d71bbbf474f2ab05ba22ebdf7 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-build-swift %s -module-name=test -DENCODE -o %t/encode
// RUN: %target-build-swift %s -module-name=test -o %t/decode
// RUN: %target-build-swift %s -module-name=test -Xfrontend -disable-llvm-optzns -emit-ir | %FileCheck -check-prefix=CHECK-IR %s
// RUN: %target-run %t/encode %t/test.arc
// RUN: plutil -p %t/test.arc | %FileCheck -check-prefix=CHECK-ARCHIVE %s
// RUN: %target-run %t/decode %t/test.arc | %FileCheck %s
// REQUIRES: executable_test
// REQUIRES: objc_interop
// REQUIRES: CPU=i386 || CPU=x86_64
// UNSUPPORTED: OS=tvos
// UNSUPPORTED: OS=watchos
import Foundation
struct ABC {
// CHECK-ARCHIVE-DAG: "$classname" => "nested_class_coding"
@objc(nested_class_coding)
class NestedClass : NSObject, NSCoding {
var i : Int
init(_ ii: Int) {
i = ii
}
required init(coder aDecoder: NSCoder) {
i = aDecoder.decodeInteger(forKey: "i")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(i, forKey: "i")
}
}
}
// CHECK-ARCHIVE-DAG: "$classname" => "private_class_coding"
@objc(private_class_coding)
private class PrivateClass : NSObject, NSCoding {
var pi : Int
init(_ ii: Int) {
pi = ii
}
required init(coder aDecoder: NSCoder) {
pi = aDecoder.decodeInteger(forKey: "pi")
}
func encode(with aCoder: NSCoder) {
aCoder.encode(pi, forKey: "pi")
}
}
class GenericClass<T> : NSObject, NSCoding {
var gi : T? = nil
override init() {
}
required init(coder aDecoder: NSCoder) {
}
func encode(with aCoder: NSCoder) {
}
}
// CHECK-ARCHIVE-DAG: "$classname" => "test.IntClass"
class IntClass : GenericClass<Int> {
init(ii: Int) {
super.init()
gi = ii
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
gi = aDecoder.decodeInteger(forKey: "gi")
}
override func encode(with aCoder: NSCoder) {
aCoder.encode(gi!, forKey: "gi")
}
}
// CHECK-ARCHIVE-DAG: "$classname" => "double_class_coding"
@objc(double_class_coding)
class DoubleClass : GenericClass<Double> {
init(dd: Double) {
super.init()
gi = dd
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
gi = aDecoder.decodeDouble(forKey: "gi")
}
override func encode(with aCoder: NSCoder) {
aCoder.encode(gi!, forKey: "gi")
}
}
// CHECK-ARCHIVE-DAG: "$classname" => "top_level_coding"
@objc(top_level_coding)
class TopLevel : NSObject, NSCoding {
var tli : Int
var nested: ABC.NestedClass?
fileprivate var priv: PrivateClass?
var intc : IntClass?
var doublec : DoubleClass?
init(_ ii: Int) {
tli = ii
}
required init(coder aDecoder: NSCoder) {
tli = aDecoder.decodeInteger(forKey: "tli")
nested = aDecoder.decodeObject(forKey: "nested") as? ABC.NestedClass
priv = aDecoder.decodeObject(forKey: "priv") as? PrivateClass
intc = aDecoder.decodeObject(forKey: "int") as? IntClass
doublec = aDecoder.decodeObject(forKey: "double") as? DoubleClass
}
func encode(with aCoder: NSCoder) {
aCoder.encode(tli, forKey: "tli")
aCoder.encode(nested, forKey: "nested")
aCoder.encode(priv, forKey: "priv")
aCoder.encode(intc, forKey: "int")
aCoder.encode(doublec, forKey: "double")
}
}
func main() {
let args = CommandLine.arguments
#if ENCODE
let c = TopLevel(27)
c.nested = ABC.NestedClass(28)
c.priv = PrivateClass(29)
c.intc = IntClass(ii: 42)
c.doublec = DoubleClass(dd: 3.14)
NSKeyedArchiver.archiveRootObject(c, toFile: args[1])
#else
if let u = NSKeyedUnarchiver.unarchiveObject(withFile: args[1]) {
if let x = u as? TopLevel {
// CHECK: top-level: 27
print("top-level: \(x.tli)")
if let n = x.nested {
// CHECK: nested: 28
print("nested: \(n.i)")
}
if let p = x.priv {
// CHECK: private: 29
print("private: \(p.pi)")
}
if let g = x.intc {
// CHECK: int: 42
print("int: \(g.gi!)")
}
if let d = x.doublec {
// CHECK: double: 3.14
print("double: \(d.gi!)")
}
} else {
print(u)
}
} else {
print("nil")
}
#endif
}
main()
// Check that we eagerly create metadata of generic classes, but not for nested classes.
// CHECK-IR-LABEL: define {{.*}} @_swift_eager_class_initialization
// CHECK-IR-NEXT: entry:
// CHECK-IR-NEXT: call {{.*}}IntClassCMa
// CHECK-IR-NEXT: extractvalue
// CHECK-IR-NEXT: call void asm
// CHECK-IR-NEXT: call {{.*}}DoubleClassCMa
// CHECK-IR-NEXT: extractvalue
// CHECK-IR-NEXT: call void asm
// CHECK-IR-NEXT: ret