Files
swift-mirror/test/Interpreter/objc_class_resilience.swift
Slava Pestov 1851630e81 IRGen: Fix crash with empty-sized field in a class with resilient ancestry
The problem was that HasObjCAncestry was not getting set if
HasResilientAncestry was true, and thus emitFieldOffsetGlobals() was
marking the field offset as const even though the Objective-C
runtime might slide it.

Fixes <rdar://problem/48031465>.
2020-04-27 19:41:42 -04:00

162 lines
4.6 KiB
Swift

// RUN: %empty-directory(%t)
// RUN: %target-clang -fobjc-arc %S/Inputs/ObjCClasses/ObjCClasses.m -c -o %t/ObjCClasses.o
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_struct)) -enable-library-evolution %S/../Inputs/resilient_struct.swift -emit-module -emit-module-path %t/resilient_struct.swiftmodule -module-name resilient_struct
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -enable-library-evolution %S/Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule -module-name resilient_objc_class -I %S/Inputs/ObjCClasses/ -L %t -Xlinker %t/ObjCClasses.o -framework Foundation
// RUN: %target-codesign %t/%target-library-name(resilient_struct) %t/%target-library-name(resilient_objc_class)
// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_objc_class -I %S/Inputs/ObjCClasses/ -o %t/main %target-rpath(%t)
// RUN: %target-codesign %t/main
// RUN: %target-run %t/main %t/%target-library-name(resilient_struct) %t/%target-library-name(resilient_objc_class)
// REQUIRES: executable_test
// REQUIRES: objc_interop
import StdlibUnittest
import Foundation
import resilient_struct
import resilient_objc_class
import ObjCClasses
var ResilientClassTestSuite = TestSuite("ResilientClass")
class ResilientFieldWithCategory {
var value: ResilientInt?
}
@objc protocol MyProtocol {
func myMethod() -> Int
}
extension ResilientFieldWithCategory : MyProtocol {
@objc func myMethod() -> Int { return 42 }
}
func takesMyProtocol(_ p: MyProtocol) -> Int {
return p.myMethod()
}
ResilientClassTestSuite.test("Category")
.xfail(.osxMinor(10, 9, reason:
"Category attachment with ARCLite on 10.9 doesn't work currently"))
.code {
expectEqual(42, takesMyProtocol(ResilientFieldWithCategory()))
}
// rdar://problem/45569020 - Make sure we initialize the superclass first
class ResilientSuperclass {
var value: ResilientInt?
}
class ResilientSubclass : ResilientSuperclass {}
ResilientClassTestSuite.test("Superclass") {
_blackHole(ResilientSubclass())
}
// rdar://48031465 - Make sure we handle sliding empty ivars properly.
struct Empty {}
class ClassWithEmptyThenResilient : HasHiddenIvars {
let empty: Empty
let resilient: ResilientInt
init(empty: Empty, resilient: ResilientInt) {
self.empty = empty
self.resilient = resilient
}
}
ResilientClassTestSuite.test("EmptyThenResilient") {
let c = ClassWithEmptyThenResilient(empty: Empty(),
resilient: ResilientInt(i: 17))
c.x = 100
c.y = 2000
c.z = 30000
c.t = 400000
expectEqual(c.resilient.i, 17)
expectEqual(c.x, 100)
expectEqual(c.y, 2000)
expectEqual(c.z, 30000)
expectEqual(c.t, 400000)
}
class ClassWithResilientThenEmpty : HasHiddenIvars {
let resilient: ResilientInt
let empty: Empty
init(empty: Empty, resilient: ResilientInt) {
self.empty = empty
self.resilient = resilient
}
}
ResilientClassTestSuite.test("ResilientThenEmpty") {
let c = ClassWithResilientThenEmpty(empty: Empty(),
resilient: ResilientInt(i: 17))
c.x = 100
c.y = 2000
c.z = 30000
c.t = 400000
expectEqual(c.resilient.i, 17)
expectEqual(c.x, 100)
expectEqual(c.y, 2000)
expectEqual(c.z, 30000)
expectEqual(c.t, 400000)
}
// Same as the above, but the class itself has a resilient base class
class AnotherClassWithEmptyThenResilient : HasResilientObjCBaseClass {
let empty: Empty
let resilient: ResilientInt
init(empty: Empty, resilient: ResilientInt) {
self.empty = empty
self.resilient = resilient
}
}
ResilientClassTestSuite.test("AnotherEmptyThenResilient") {
let c = AnotherClassWithEmptyThenResilient(empty: Empty(),
resilient: ResilientInt(i: 17))
c.x = 100
c.y = 2000
c.z = 30000
c.t = 400000
expectEqual(c.resilient.i, 17)
expectEqual(c.x, 100)
expectEqual(c.y, 2000)
expectEqual(c.z, 30000)
expectEqual(c.t, 400000)
}
class AnotherClassWithResilientThenEmpty : HasHiddenIvars {
let resilient: ResilientInt
let empty: Empty
init(empty: Empty, resilient: ResilientInt) {
self.empty = empty
self.resilient = resilient
}
}
ResilientClassTestSuite.test("AnotherResilientThenEmpty") {
let c = AnotherClassWithResilientThenEmpty(empty: Empty(),
resilient: ResilientInt(i: 17))
c.x = 100
c.y = 2000
c.z = 30000
c.t = 400000
expectEqual(c.resilient.i, 17)
expectEqual(c.x, 100)
expectEqual(c.y, 2000)
expectEqual(c.z, 30000)
expectEqual(c.t, 400000)
}
runAllTests()