mirror of
https://github.com/apple/swift.git
synced 2026-10-26 20:15:53 +01:00
Previously, when a derived class re-stated a SWIFT_SHARED_REFERENCE annotation (or any other reference type annotation), ClangImporter would allow upcasting to its base if the retain/release op *strings* matched the base's. This is unsound: two unrelated classes that happen to name their retain/release ops the same way would be considered upcast-able, and a string match between overriding methods doesn't actually guarantee that calling the base's retain/release op on a derived pointer is correct. This change removes the string-matching upcast logic. An explicit annotation on a class now acts as an upcast barrier: the class is imported as a foreign reference type with no Swift superclass, regardless of whether its base is also an FRT. To participate in the FRT inheritance chain, intermediate classes should inherit the annotation from their base instead of re-stating it. rdar://179748445
67 lines
2.1 KiB
Swift
67 lines
2.1 KiB
Swift
// RUN: %target-swift-ide-test -print-module -module-to-print=Upcast -I %S/Inputs -I %swift_src_root/lib/ClangImporter/SwiftBridging -source-filename=x -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature ForeignReferenceTypeInheritance -print-implicit-attrs | %FileCheck %s
|
|
|
|
// REQUIRES: swift_feature_ForeignReferenceTypeInheritance
|
|
|
|
// CHECK: class Base {
|
|
// CHECK: var baseValue: Int32
|
|
// CHECK: func getBaseValue() -> Int32
|
|
// CHECK: func setBaseValue(_ v: Int32)
|
|
// CHECK: class func create() -> Base
|
|
// CHECK: }
|
|
|
|
// CHECK: class Derived : Base {
|
|
// CHECK: var derivedValue: Int32
|
|
// CHECK: func getDerivedValue() -> Int32
|
|
// CHECK: override class func create() -> Derived
|
|
// CHECK: }
|
|
|
|
// CHECK: class LeafDerived : Derived {
|
|
// CHECK: var leafValue: Int32
|
|
// CHECK: func getLeafValue() -> Int32
|
|
// CHECK: override class func create() -> LeafDerived
|
|
// CHECK: }
|
|
|
|
// CHECK: class Unrelated {
|
|
// CHECK: var unrelatedValue: Int32
|
|
// CHECK: class func create() -> Unrelated
|
|
// CHECK: }
|
|
|
|
// Virtual base: no Swift superclass relationship.
|
|
// CHECK: class VirtualDerived {
|
|
|
|
// CHECK: class RefCountedBase {
|
|
// CHECK: var baseField: Int32
|
|
// CHECK: func getBaseValue() -> Int32
|
|
// CHECK: class func create() -> RefCountedBase
|
|
// CHECK: }
|
|
|
|
// CHECK: class RefCountedDerived : RefCountedBase {
|
|
// CHECK: var derivedField: Int32
|
|
// CHECK: func getDerivedField() -> Int32
|
|
// CHECK: override class func create() -> RefCountedDerived
|
|
// CHECK: }
|
|
|
|
// CHECK: class OverridesLifetimeOps {
|
|
|
|
// CHECK: class OverridesLifetimeOpsDerived {
|
|
|
|
// CHECK: class ReannotatedRefCountedDerived {
|
|
|
|
// CHECK: class DerivedFromEmptyAndBase : Base {
|
|
// CHECK: var extraValue: Int32
|
|
// CHECK: func getExtraValue() -> Int32
|
|
// CHECK: override class func create() -> DerivedFromEmptyAndBase
|
|
// CHECK: }
|
|
|
|
// CHECK: class CRTPBase<CRTPDerived> {
|
|
// CHECK: var crtpBaseValue: Int32
|
|
// CHECK: func derivedSelf() -> CRTPDerived!
|
|
// CHECK: }
|
|
|
|
// CHECK: class CRTPDerived : CRTPBase<CRTPDerived> {
|
|
// CHECK: var crtpDerivedValue: Int32
|
|
// CHECK: class func create() -> CRTPDerived
|
|
// CHECK: }
|
|
|
|
// CHECK: typealias CRTPBaseOfDerived = CRTPBase<CRTPDerived>
|