Skip to content

Commit 41dfeef

Browse files
authored
Merge pull request #9821 from swiftix/conditional-bridging-downcast-bailout
[cast-optimizer] Bail out on a downcast to a subclass of a bridged ObjC class
2 parents 9520aff + 62e1944 commit 41dfeef

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lib/SILOptimizer/Utils/Local.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1461,6 +1461,13 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
14611461
auto &M = Inst->getModule();
14621462
auto Loc = Inst->getLoc();
14631463

1464+
// FIXME (rdar://problem/32319580): The code below handles a cast from a Swift
1465+
// value type to a subclass of its bridged type by emitting an unconditional
1466+
// cast, even if the cast is supposed to be conditional.
1467+
if (isConditional && !BridgedSourceTy->isEqual(BridgedTargetTy) &&
1468+
BridgedSourceTy->isBindableToSuperclassOf(BridgedTargetTy))
1469+
return nullptr;
1470+
14641471
bool AddressOnlyType = false;
14651472
if (!Src->getType().isLoadable(M) || !Dest->getType().isLoadable(M)) {
14661473
AddressOnlyType = true;

test/SILOptimizer/cast_folding_objc.swift

+34
Original file line numberDiff line numberDiff line change
@@ -265,3 +265,37 @@ public func testBridgedCastFromSwiftToObjC(_ s: String) -> NSString {
265265
return s as NSString
266266
}
267267

268+
public class MyString: NSString {}
269+
270+
// Check that the cast-optimizer bails out on a conditional downcast to a subclass of a
271+
// bridged ObjC class.
272+
// CHECK-LABEL: sil [noinline] @{{.*}}testConditionalBridgedCastFromSwiftToNSObjectDerivedClass{{.*}}
273+
// CHECK-NOT: apply
274+
// CHECK-NOT: unconditional
275+
// CHECK-NOT: checked_cast_br
276+
// CHECK: checked_cast_addr_br
277+
// CHECK-NOT: apply
278+
// CHECK-NOT: unconditional
279+
// CHECK-NOT: checked_cast_br
280+
// CHECK: return
281+
@inline(never)
282+
public func testConditionalBridgedCastFromSwiftToNSObjectDerivedClass(_ s: String) -> MyString? {
283+
return s as? MyString
284+
}
285+
286+
// Check that the cast-optimizer does not bail out on an unconditional downcast to a subclass of a
287+
// bridged ObjC class.
288+
// CHECK-LABEL: sil [noinline] @{{.*}}testForcedBridgedCastFromSwiftToNSObjectDerivedClass{{.*}}
289+
// CHECK: function_ref @_T0SS10FoundationE19_bridgeToObjectiveC{{[_0-9a-zA-Z]*}}F
290+
// CHECK: apply
291+
// CHECK-NOT: apply
292+
// CHECK-NOT: checked_cast_br
293+
// CHECK: unconditional_checked_cast
294+
// CHECK-NOT: apply
295+
// CHECK-NOT: unconditional
296+
// CHECK-NOT: checked_cast
297+
// CHECK: return
298+
@inline(never)
299+
public func testForcedBridgedCastFromSwiftToNSObjectDerivedClass(_ s: String) -> MyString {
300+
return s as! MyString
301+
}

0 commit comments

Comments
 (0)