Skip to content

Commit 84b4efc

Browse files
authored
Merge pull request #17247 from DougGregor/import-objc-generic-of-block
[Clang importer] Don't bridge blocks to Swift functions in ObjC generic args
2 parents 4051246 + f595ca7 commit 84b4efc

File tree

5 files changed

+41
-8
lines changed

5 files changed

+41
-8
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -974,8 +974,8 @@ namespace {
974974
// Convert the type arguments.
975975
for (auto typeArg : typeArgs) {
976976
Type importedTypeArg = Impl.importTypeIgnoreIUO(
977-
typeArg, ImportTypeKind::BridgedValue, AllowNSUIntegerAsInt,
978-
Bridging, OTK_None);
977+
typeArg, ImportTypeKind::ObjCCollectionElement,
978+
AllowNSUIntegerAsInt, Bridging, OTK_None);
979979
if (!importedTypeArg) {
980980
importedTypeArgs.clear();
981981
break;
@@ -1102,7 +1102,7 @@ static bool canBridgeTypes(ImportTypeKind importKind) {
11021102
case ImportTypeKind::CFUnretainedOutParameter:
11031103
case ImportTypeKind::Property:
11041104
case ImportTypeKind::PropertyWithReferenceSemantics:
1105-
case ImportTypeKind::BridgedValue:
1105+
case ImportTypeKind::ObjCCollectionElement:
11061106
case ImportTypeKind::Typedef:
11071107
return true;
11081108
}
@@ -1116,7 +1116,7 @@ static bool isCFAudited(ImportTypeKind importKind) {
11161116
case ImportTypeKind::Abstract:
11171117
case ImportTypeKind::Typedef:
11181118
case ImportTypeKind::Value:
1119-
case ImportTypeKind::BridgedValue:
1119+
case ImportTypeKind::ObjCCollectionElement:
11201120
case ImportTypeKind::Variable:
11211121
case ImportTypeKind::Result:
11221122
case ImportTypeKind::Pointee:
@@ -1287,10 +1287,24 @@ static ImportedType adjustTypeForConcreteImport(
12871287
// we would prefer to instead use the default Swift convention.
12881288
if (hint == ImportHint::Block) {
12891289
if (canBridgeTypes(importKind)) {
1290+
// Determine the function type representation we need.
1291+
//
1292+
// For Objective-C collection arguments, we cannot bridge from a block
1293+
// to a Swift function type, so force the block representation. Normally
1294+
// the mapped type will have a block representation (making this a no-op),
1295+
// but in cases where the Clang type was written as a typedef of a
1296+
// block type, that typedef will have a Swift function type
1297+
// representation. This code will then break down the imported type
1298+
// alias and produce a function type with block representation.
1299+
auto requiredFunctionTypeRepr = FunctionTypeRepresentation::Swift;
1300+
if (importKind == ImportTypeKind::ObjCCollectionElement) {
1301+
requiredFunctionTypeRepr = FunctionTypeRepresentation::Block;
1302+
}
1303+
12901304
auto fTy = importedType->castTo<FunctionType>();
12911305
FunctionType::ExtInfo einfo = fTy->getExtInfo();
1292-
if (einfo.getRepresentation() != FunctionTypeRepresentation::Swift) {
1293-
einfo = einfo.withRepresentation(FunctionTypeRepresentation::Swift);
1306+
if (einfo.getRepresentation() != requiredFunctionTypeRepr) {
1307+
einfo = einfo.withRepresentation(requiredFunctionTypeRepr);
12941308
importedType = fTy->withExtInfo(einfo);
12951309
}
12961310
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ enum class ImportTypeKind {
108108
/// \brief Import the type of a literal value.
109109
Value,
110110

111-
/// \brief Import the type of a literal value that can be bridged.
112-
BridgedValue,
111+
/// \brief Import the type of an Objective-C generic argument.
112+
ObjCCollectionElement,
113113

114114
/// \brief Import the declared type of a variable.
115115
Variable,

test/ClangImporter/objc_bridging_generics.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,3 +414,7 @@ func testHashableGenerics(
414414
let _: Int = insufficient.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}}
415415
let _: Int = extra.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}}
416416
}
417+
418+
func testGenericsWithTypedefBlocks(hba: HasBlockArray) {
419+
let _: Int = hba.blockArray() // expected-error{{type '[@convention(block) () -> Void]'}}
420+
}

test/ClangImporter/objc_ir.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Foundation
1313
import objc_ext
1414
import TestProtocols
1515
import ObjCIRExtras
16+
import objc_generics
1617

1718
// CHECK: @"\01L_selector_data(method:withFloat:)" = private global [18 x i8] c"method:withFloat:\00"
1819
// CHECK: @"\01L_selector_data(method:withDouble:)" = private global [19 x i8] c"method:withDouble:\00"
@@ -344,6 +345,13 @@ func testConstrGenericCompatibilityAliasMangling(constr_generic_obj: SwiftConstr
344345
// CHECK: call void @llvm.dbg.declare(metadata %TSo26SwiftConstrGenericNameTestCySo8NSNumberCG** {{%.+}}, metadata ![[SWIFT_CONSTR_GENERIC_NAME_ALIAS_VAR:[0-9]+]], metadata !DIExpression())
345346
}
346347

348+
// CHECK-LABEL: S7objc_ir22testBlocksWithGenerics3hbaypSo13HasBlockArrayC_tF
349+
func testBlocksWithGenerics(hba: HasBlockArray) -> Any {
350+
// CHECK: {{call swiftcc.*SSo13HasBlockArrayC05blockC0SayyyXBGyFTcTO}}
351+
let _ = hba.blockPointerType()
352+
return hba.blockArray
353+
}
354+
347355
// CHECK: linkonce_odr hidden {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfcTO"
348356
// CHECK: load i8*, i8** @"\01L_selector(initWithInt:)"
349357
// CHECK: call [[OPAQUE:%.*]]* bitcast (void ()* @objc_msgSend

test/Inputs/clang-importer-sdk/usr/include/objc_generics.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,10 @@ typedef id <Fungible> FungibleObject;
113113

114114
@interface Third : Second<Third *>
115115
@end
116+
117+
typedef void (^ _Nonnull BlockPointerType)(void);
118+
119+
@interface HasBlockArray : NSObject
120+
- (NSArray<BlockPointerType> * _Nonnull)blockArray;
121+
- (BlockPointerType)blockPointerType;
122+
@end

0 commit comments

Comments
 (0)