Skip to content

Commit 9792d6e

Browse files
authored
Merge pull request #17261 from DougGregor/import-array-of-block-4.2-06-11-2018
[4.2 2018-06-11] [Clang importer] Don't bridge blocks to Swift functions in ObjC generic arguments.
2 parents 876917f + cfd730a commit 9792d6e

File tree

5 files changed

+44
-10
lines changed

5 files changed

+44
-10
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 23 additions & 8 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:
@@ -1283,14 +1283,29 @@ static ImportedType adjustTypeForConcreteImport(
12831283
}
12841284

12851285
// SwiftTypeConverter turns block pointers into @convention(block) types.
1286-
// In a bridgeable context, or in the direct structure of a typedef,
1287-
// we would prefer to instead use the default Swift convention.
1286+
// In some contexts, we bridge them to use the Swift function type
1287+
// representation. This includes typedefs of block types, which use the
1288+
// Swift function type representation.
12881289
if (hint == ImportHint::Block) {
12891290
if (canBridgeTypes(importKind)) {
1291+
// Determine the function type representation we need.
1292+
//
1293+
// For Objective-C collection arguments, we cannot bridge from a block
1294+
// to a Swift function type, so force the block representation. Normally
1295+
// the mapped type will have a block representation (making this a no-op),
1296+
// but in cases where the Clang type was written as a typedef of a
1297+
// block type, that typedef will have a Swift function type
1298+
// representation. This code will then break down the imported type
1299+
// alias and produce a function type with block representation.
1300+
auto requiredFunctionTypeRepr = FunctionTypeRepresentation::Swift;
1301+
if (importKind == ImportTypeKind::ObjCCollectionElement) {
1302+
requiredFunctionTypeRepr = FunctionTypeRepresentation::Block;
1303+
}
1304+
12901305
auto fTy = importedType->castTo<FunctionType>();
12911306
FunctionType::ExtInfo einfo = fTy->getExtInfo();
1292-
if (einfo.getRepresentation() != FunctionTypeRepresentation::Swift) {
1293-
einfo = einfo.withRepresentation(FunctionTypeRepresentation::Swift);
1307+
if (einfo.getRepresentation() != requiredFunctionTypeRepr) {
1308+
einfo = einfo.withRepresentation(requiredFunctionTypeRepr);
12941309
importedType = fTy->withExtInfo(einfo);
12951310
}
12961311
}

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"
@@ -337,6 +338,13 @@ func testCompatibilityAliasMangling(obj: SwiftNameAlias) {
337338
}
338339

339340

341+
// CHECK-LABEL: S7objc_ir22testBlocksWithGenerics3hbaypSo13HasBlockArrayC_tF
342+
func testBlocksWithGenerics(hba: HasBlockArray) -> Any {
343+
// CHECK: {{call swiftcc.*SSo13HasBlockArrayC05blockC0SayyyXBGyFTcTO}}
344+
let _ = hba.blockPointerType()
345+
return hba.blockArray
346+
}
347+
340348
// CHECK: linkonce_odr hidden {{.*}} @"$SSo1BC3intABSgs5Int32V_tcfcTO"
341349
// CHECK: load i8*, i8** @"\01L_selector(initWithInt:)"
342350
// 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
@@ -112,3 +112,10 @@ typedef id <Fungible> FungibleObject;
112112

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

0 commit comments

Comments
 (0)