Skip to content

Commit 8464b77

Browse files
authored
Merge pull request #81251 from eeckstein/fix-objc-class-casting-6.2
[6.2] CastOptimizer: don't assume dynamic casts from ObjectiveC classes to unrelated classes will fail
2 parents e767e7f + bcc9753 commit 8464b77

File tree

4 files changed

+19
-18
lines changed

4 files changed

+19
-18
lines changed

lib/SIL/Utils/DynamicCasts.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,10 @@ swift::classifyDynamicCast(SILFunction *function,
741741
if (targetClass->isSuperclassOf(sourceClass))
742742
return DynamicCastFeasibility::WillSucceed;
743743

744-
return DynamicCastFeasibility::WillFail;
744+
// In case of ObjectiveC classes, the runtime type can differ from its
745+
// declared type. Therefore a cast between (compile-time) unrelated
746+
// classes may succeed at runtime.
747+
return DynamicCastFeasibility::MaySucceed;
745748
}
746749
}
747750

@@ -750,6 +753,12 @@ swift::classifyDynamicCast(SILFunction *function,
750753
if (hierarchyResult != DynamicCastFeasibility::WillFail)
751754
return hierarchyResult;
752755

756+
// In case of ObjectiveC classes, the runtime type can differ from its
757+
// declared type. Therefore a cast between (compile-time) unrelated
758+
// classes may succeed at runtime.
759+
if (sourceClass->hasClangNode())
760+
return DynamicCastFeasibility::MaySucceed;
761+
753762
// As a backup, consider whether either type is a CF class type
754763
// with an NS bridged equivalent.
755764
CanType bridgedSource = getNSBridgedClassOfCFClass(source);

test/Interpreter/bridged_casts_folding.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Tests.test("NSString => Array<Int>. Crashing test case") {
5858
// CHECK: [ OK ] BridgedCastFolding.NSString => Array<Int>. Crashing test case
5959

6060
// CHECK-OPT-LABEL: [ RUN ] BridgedCastFolding.NSString => Array<Int>. Crashing test case
61-
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sig{{ill|trap}}"
61+
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sigabrt"
6262
// CHECK-OPT: [ OK ] BridgedCastFolding.NSString => Array<Int>. Crashing test case
6363
expectCrashLater()
6464
do {
@@ -130,7 +130,7 @@ Tests.test("NSNumber (Int) -> String. Crashing test.") {
130130
// CHECK: [ OK ] BridgedCastFolding.NSNumber (Int) -> String. Crashing test.
131131

132132
// CHECK-OPT-LABEL: [ RUN ] BridgedCastFolding.NSNumber (Int) -> String. Crashing test.
133-
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sig{{ill|trap}}"
133+
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sigabrt"
134134
// CHECK-OPT: [ OK ] BridgedCastFolding.NSNumber (Int) -> String. Crashing test.
135135
expectCrashLater()
136136
do {
@@ -393,7 +393,7 @@ Tests.test("String -> NSNumber. Crashing Test Case") {
393393
// CHECK: [ OK ] BridgedCastFolding.String -> NSNumber. Crashing Test Case
394394

395395
// CHECK-OPT-LABEL: [ RUN ] BridgedCastFolding.String -> NSNumber. Crashing Test Case
396-
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sig{{ill|trap}}"
396+
// CHECK-OPT: stderr>>> OK: saw expected "crashed: sigabrt"
397397
// CHECK-OPT: [ OK ] BridgedCastFolding.String -> NSNumber. Crashing Test Case
398398
expectCrashLater()
399399
do {

test/SILOptimizer/cast_folding_no_bridging.sil

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,8 @@ bb3:
6464
sil @fail : $@convention(thin) () -> Never
6565

6666
// CHECK-LABEL: sil {{.*}}@testCFToObjC
67-
// CHECK: bb0(
68-
// CHECK-NEXT: [[T0:%.*]] = load %1 : $*CFString
69-
// CHECK-NEXT: [[T1:%.*]] = unchecked_ref_cast [[T0]] : $CFString to $NSString
70-
// CHECK-NEXT: store [[T1]] to %0 : $*NSString
67+
// CHECK: checked_cast_addr_br
68+
// CHECK: } // end sil function 'testCFToObjC'
7169
sil @testCFToObjC : $@convention(thin) (@in CFString) -> @out NSString {
7270
bb0(%0 : $*NSString, %1 : $*CFString):
7371
checked_cast_addr_br take_always CFString in %1 : $*CFString to NSString in %0 : $*NSString, bb1, bb2
@@ -83,11 +81,8 @@ bb2:
8381
}
8482

8583
// CHECK-LABEL: sil {{.*}}@testCFToSwift
86-
// CHECK: bb0(
87-
// CHECK-NEXT: [[T0:%.*]] = load %1 : $*CFString
88-
// CHECK-NEXT: [[T1:%.*]] = unchecked_ref_cast [[T0]] : $CFString to $NSString
89-
// CHECK: [[FN:%.*]] = function_ref @$sSS10FoundationE34_conditionallyBridgeFromObjectiveC_6resultSbSo8NSStringC_SSSgztFZ : $@convention(method) (@guaranteed NSString, @inout Optional<String>, @thin String.Type) -> Bool
90-
// CHECK: apply [[FN]]([[T1]], {{.*}}, {{.*}})
84+
// CHECK: checked_cast
85+
// CHECK: } // end sil function 'testCFToSwift'
9186
sil @testCFToSwift : $@convention(thin) (@in CFString) -> @out String {
9287
bb0(%0 : $*String, %1 : $*CFString):
9388
checked_cast_addr_br take_always CFString in %1 : $*CFString to String in %0 : $*String, bb1, bb2

test/SILOptimizer/cast_folding_objc.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,9 @@ public func castObjCToSwift<T>(_ t: T) -> Int {
7777
return t as! Int
7878
}
7979

80-
// Check that compiler understands that this cast always fails
8180
// CHECK-LABEL: sil [noinline] {{.*}}@$s17cast_folding_objc37testFailingBridgedCastFromObjCtoSwiftySiSo8NSStringCF
82-
// CHECK: [[ONE:%[0-9]+]] = integer_literal $Builtin.Int1, -1
83-
// CHECK: cond_fail [[ONE]] : $Builtin.Int1, "failed cast"
84-
// CHECK-NEXT: unreachable
85-
// CHECK-NEXT: }
81+
// CHECK: unconditional_checked_cast %0 : $NSString to NSNumber
82+
// CHECK: } // end sil function '$s17cast_folding_objc37testFailingBridgedCastFromObjCtoSwiftySiSo8NSStringCF'
8683
@inline(never)
8784
public func testFailingBridgedCastFromObjCtoSwift(_ ns: NSString) -> Int {
8885
return castObjCToSwift(ns)

0 commit comments

Comments
 (0)