mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[cast-optimizer] Properly handle conditional bridged casts in optimizeBridgedSwiftToObjCCast
If there is a conditional bridged cast from a swift type to an objc type and this cast happens in two stages, where: - in the firs stage the Swift type is casted to its bridged ObjC class (e.g. String to NSString) and - in the second stage there is a downcast to a subclass of a bridged ObjC class (e.g. NSString to MyString) then the second stage should use a conditional cast. rdar://32319580
This commit is contained in:
@@ -1461,13 +1461,6 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
|
||||
auto &M = Inst->getModule();
|
||||
auto Loc = Inst->getLoc();
|
||||
|
||||
// FIXME (rdar://problem/32319580): The code below handles a cast from a Swift
|
||||
// value type to a subclass of its bridged type by emitting an unconditional
|
||||
// cast, even if the cast is supposed to be conditional.
|
||||
if (isConditional && !BridgedSourceTy->isEqual(BridgedTargetTy) &&
|
||||
BridgedSourceTy->isBindableToSuperclassOf(BridgedTargetTy))
|
||||
return nullptr;
|
||||
|
||||
bool AddressOnlyType = false;
|
||||
if (!Src->getType().isLoadable(M) || !Dest->getType().isLoadable(M)) {
|
||||
AddressOnlyType = true;
|
||||
@@ -1663,8 +1656,21 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
|
||||
CastedValue = SILValue(
|
||||
(ConvTy == DestTy) ? NewI : Builder.createUpcast(Loc, NewAI, DestTy));
|
||||
} else if (ConvTy.isExactSuperclassOf(DestTy)) {
|
||||
CastedValue = SILValue(
|
||||
Builder.createUnconditionalCheckedCast(Loc, NewAI, DestTy));
|
||||
// The downcast from a base class to derived class may fail.
|
||||
if (isConditional) {
|
||||
// In case of a conditional cast, we should handle it gracefully.
|
||||
auto CondBrSuccessBB =
|
||||
NewAI->getFunction()->createBasicBlock(NewAI->getParentBlock());
|
||||
CondBrSuccessBB->createPHIArgument(DestTy, ValueOwnershipKind::Owned,
|
||||
nullptr);
|
||||
Builder.createCheckedCastBranch(Loc, /* isExact*/ false, NewAI, DestTy,
|
||||
CondBrSuccessBB, FailureBB);
|
||||
Builder.setInsertionPoint(CondBrSuccessBB, CondBrSuccessBB->begin());
|
||||
CastedValue = CondBrSuccessBB->getArgument(0);
|
||||
} else {
|
||||
CastedValue = SILValue(
|
||||
Builder.createUnconditionalCheckedCast(Loc, NewAI, DestTy));
|
||||
}
|
||||
} else if (ConvTy.getSwiftRValueType() ==
|
||||
getNSBridgedClassOfCFClass(M.getSwiftModule(),
|
||||
DestTy.getSwiftRValueType()) ||
|
||||
@@ -1681,6 +1687,9 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
|
||||
}
|
||||
NewI = Builder.createStore(Loc, CastedValue, Dest,
|
||||
StoreOwnershipQualifier::Unqualified);
|
||||
if (isConditional && NewI->getParentBlock() != NewAI->getParentBlock()) {
|
||||
Builder.createBranch(Loc, SuccessBB);
|
||||
}
|
||||
}
|
||||
|
||||
if (Dest) {
|
||||
|
||||
Reference in New Issue
Block a user