@@ -1194,6 +1194,85 @@ static bool isNSString(Type type) {
1194
1194
return false ;
1195
1195
}
1196
1196
1197
+ static Type maybeImportNSErrorOutParameter (ClangImporter::Implementation &impl,
1198
+ Type importedType,
1199
+ bool resugarNSErrorPointer) {
1200
+ PointerTypeKind PTK;
1201
+ auto elementType = importedType->getAnyPointerElementType (PTK);
1202
+ if (!elementType || PTK != PTK_AutoreleasingUnsafeMutablePointer)
1203
+ return Type ();
1204
+
1205
+ auto elementObj = elementType->getOptionalObjectType ();
1206
+ if (!elementObj)
1207
+ return Type ();
1208
+
1209
+ auto elementClass = elementObj->getClassOrBoundGenericClass ();
1210
+ if (!elementClass)
1211
+ return Type ();
1212
+
1213
+ // FIXME: Avoid string comparison by caching this identifier.
1214
+ if (elementClass->getName ().str () !=
1215
+ impl.SwiftContext .getSwiftName (KnownFoundationEntity::NSError))
1216
+ return Type ();
1217
+
1218
+ ModuleDecl *foundationModule = impl.tryLoadFoundationModule ();
1219
+ if (!foundationModule ||
1220
+ foundationModule->getName ()
1221
+ != elementClass->getModuleContext ()->getName ())
1222
+ return Type ();
1223
+
1224
+
1225
+ if (resugarNSErrorPointer)
1226
+ return impl.getNamedSwiftType (
1227
+ foundationModule,
1228
+ impl.SwiftContext .getSwiftName (
1229
+ KnownFoundationEntity::NSErrorPointer));
1230
+
1231
+ // The imported type is AUMP<NSError?>, but the typealias is AUMP<NSError?>?
1232
+ // so we have to manually make them match. We also want to assume this in
1233
+ // general for error out-parameters even if they weren't marked nullable in C.
1234
+ // Or at least we do for source-compatibility reasons...
1235
+ return OptionalType::get (importedType);
1236
+ }
1237
+
1238
+ static Type maybeImportCFOutParameter (ClangImporter::Implementation &impl,
1239
+ Type importedType,
1240
+ ImportTypeKind importKind) {
1241
+ PointerTypeKind PTK;
1242
+ auto elementType = importedType->getAnyPointerElementType (PTK);
1243
+ if (!elementType || PTK != PTK_UnsafeMutablePointer)
1244
+ return Type ();
1245
+
1246
+ auto insideOptionalType = elementType->getOptionalObjectType ();
1247
+ bool isOptional = (bool ) insideOptionalType;
1248
+ if (!insideOptionalType)
1249
+ insideOptionalType = elementType;
1250
+
1251
+ auto boundGenericTy = insideOptionalType->getAs <BoundGenericType>();
1252
+ if (!boundGenericTy)
1253
+ return Type ();
1254
+
1255
+ auto boundGenericBase = boundGenericTy->getDecl ();
1256
+ if (boundGenericBase != impl.SwiftContext .getUnmanagedDecl ())
1257
+ return Type ();
1258
+
1259
+ assert (boundGenericTy->getGenericArgs ().size () == 1 &&
1260
+ " signature of Unmanaged has changed" );
1261
+
1262
+ auto resultTy = boundGenericTy->getGenericArgs ().front ();
1263
+ if (isOptional)
1264
+ resultTy = OptionalType::get (resultTy);
1265
+
1266
+ PointerTypeKind pointerKind;
1267
+ if (importKind == ImportTypeKind::CFRetainedOutParameter)
1268
+ pointerKind = PTK_UnsafeMutablePointer;
1269
+ else
1270
+ pointerKind = PTK_AutoreleasingUnsafeMutablePointer;
1271
+
1272
+ resultTy = getPointerTo (resultTy, pointerKind);
1273
+ return resultTy;
1274
+ }
1275
+
1197
1276
static ImportedType adjustTypeForConcreteImport (
1198
1277
ClangImporter::Implementation &impl,
1199
1278
ImportResult importResult, ImportTypeKind importKind,
@@ -1217,7 +1296,6 @@ static ImportedType adjustTypeForConcreteImport(
1217
1296
1218
1297
case ImportHint::ObjCPointer:
1219
1298
case ImportHint::CFunctionPointer:
1220
- case ImportHint::OtherPointer:
1221
1299
break ;
1222
1300
1223
1301
case ImportHint::Void:
@@ -1234,7 +1312,9 @@ static ImportedType adjustTypeForConcreteImport(
1234
1312
if (isNSString (importedType)) {
1235
1313
if (importKind == ImportTypeKind::Variable ||
1236
1314
importKind == ImportTypeKind::AuditedVariable) {
1237
- return {hint.BridgedType , false };
1315
+ importedType = hint.BridgedType ;
1316
+ optKind = OTK_None;
1317
+ break ;
1238
1318
}
1239
1319
}
1240
1320
@@ -1292,14 +1372,14 @@ static ImportedType adjustTypeForConcreteImport(
1292
1372
// Turn BOOL and DarwinBoolean into Bool in contexts that can bridge types
1293
1373
// losslessly.
1294
1374
if (bridging == Bridgeability::Full && canBridgeTypes (importKind))
1295
- return { impl.SwiftContext .getBoolDecl ()->getDeclaredType (), false } ;
1375
+ importedType = impl.SwiftContext .getBoolDecl ()->getDeclaredType ();
1296
1376
break ;
1297
1377
1298
1378
case ImportHint::NSUInteger:
1299
1379
// When NSUInteger is used as an enum's underlying type or if it does not
1300
1380
// come from a system module, make sure it stays unsigned.
1301
1381
if (importKind == ImportTypeKind::Enum || !allowNSUIntegerAsInt)
1302
- return { impl.SwiftContext .getUIntDecl ()->getDeclaredType (), false } ;
1382
+ importedType = impl.SwiftContext .getUIntDecl ()->getDeclaredType ();
1303
1383
break ;
1304
1384
1305
1385
case ImportHint::CFPointer:
@@ -1328,99 +1408,33 @@ static ImportedType adjustTypeForConcreteImport(
1328
1408
optKind = OTK_None;
1329
1409
}
1330
1410
break ;
1331
- }
1332
-
1333
- assert (importedType);
1334
-
1335
- // Special case AutoreleasingUnsafeMutablePointer<NSError?> parameters.
1336
- auto maybeImportNSErrorPointer = [&]() -> Type {
1337
- if (importKind != ImportTypeKind::Parameter)
1338
- return Type ();
1339
-
1340
- PointerTypeKind PTK;
1341
- auto elementType = importedType->getAnyPointerElementType (PTK);
1342
- if (!elementType || PTK != PTK_AutoreleasingUnsafeMutablePointer)
1343
- return Type ();
1344
-
1345
- auto elementObj = elementType->getOptionalObjectType ();
1346
- if (!elementObj)
1347
- return Type ();
1348
-
1349
- auto elementClass = elementObj->getClassOrBoundGenericClass ();
1350
- if (!elementClass)
1351
- return Type ();
1352
-
1353
- // FIXME: Avoid string comparison by caching this identifier.
1354
- if (elementClass->getName ().str () !=
1355
- impl.SwiftContext .getSwiftName (KnownFoundationEntity::NSError))
1356
- return Type ();
1357
-
1358
- ModuleDecl *foundationModule = impl.tryLoadFoundationModule ();
1359
- if (!foundationModule ||
1360
- foundationModule->getName ()
1361
- != elementClass->getModuleContext ()->getName ())
1362
- return Type ();
1363
1411
1364
-
1365
- if (resugarNSErrorPointer)
1366
- return impl.getNamedSwiftType (
1367
- foundationModule,
1368
- impl.SwiftContext .getSwiftName (
1369
- KnownFoundationEntity::NSErrorPointer));
1370
-
1371
- // The imported type is AUMP<NSError?>, but the typealias is AUMP<NSError?>?
1372
- // so we have to manually make them match.
1373
- return OptionalType::get (importedType);
1374
- };
1375
-
1376
- if (Type result = maybeImportNSErrorPointer ()) {
1377
- return {result, false };
1378
- }
1379
-
1380
- auto maybeImportCFOutParameter = [&]() -> Type {
1381
- if (importKind != ImportTypeKind::CFRetainedOutParameter &&
1382
- importKind != ImportTypeKind::CFUnretainedOutParameter) {
1383
- return Type ();
1412
+ case ImportHint::OtherPointer:
1413
+ // Special-case AutoreleasingUnsafeMutablePointer<NSError?> parameters.
1414
+ if (importKind == ImportTypeKind::Parameter) {
1415
+ if (Type result = maybeImportNSErrorOutParameter (impl, importedType,
1416
+ resugarNSErrorPointer)) {
1417
+ importedType = result;
1418
+ optKind = OTK_None;
1419
+ break ;
1420
+ }
1384
1421
}
1385
1422
1386
- PointerTypeKind PTK;
1387
- auto elementType = importedType->getAnyPointerElementType (PTK);
1388
- if (!elementType || PTK != PTK_UnsafeMutablePointer)
1389
- return Type ();
1390
-
1391
- auto insideOptionalType = elementType->getOptionalObjectType ();
1392
- bool isOptional = (bool ) insideOptionalType;
1393
- if (!insideOptionalType)
1394
- insideOptionalType = elementType;
1395
-
1396
- auto boundGenericTy = insideOptionalType->getAs <BoundGenericType>();
1397
- if (!boundGenericTy)
1398
- return Type ();
1399
-
1400
- auto boundGenericBase = boundGenericTy->getDecl ();
1401
- if (boundGenericBase != impl.SwiftContext .getUnmanagedDecl ())
1402
- return Type ();
1403
-
1404
- assert (boundGenericTy->getGenericArgs ().size () == 1 &&
1405
- " signature of Unmanaged has changed" );
1406
-
1407
- auto resultTy = boundGenericTy->getGenericArgs ().front ();
1408
- if (isOptional)
1409
- resultTy = OptionalType::get (resultTy);
1410
-
1411
- PointerTypeKind pointerKind;
1412
- if (importKind == ImportTypeKind::CFRetainedOutParameter)
1413
- pointerKind = PTK_UnsafeMutablePointer;
1414
- else
1415
- pointerKind = PTK_AutoreleasingUnsafeMutablePointer;
1423
+ // Remove 'Unmanaged' from audited CF out-parameters.
1424
+ if (importKind == ImportTypeKind::CFRetainedOutParameter ||
1425
+ importKind == ImportTypeKind::CFUnretainedOutParameter) {
1426
+ if (Type outParamTy = maybeImportCFOutParameter (impl, importedType,
1427
+ importKind)) {
1428
+ importedType = outParamTy;
1429
+ break ;
1430
+ }
1431
+ }
1416
1432
1417
- resultTy = getPointerTo (resultTy, pointerKind);
1418
- return resultTy;
1419
- };
1420
- if (Type outParamTy = maybeImportCFOutParameter ()) {
1421
- importedType = outParamTy;
1433
+ break ;
1422
1434
}
1423
1435
1436
+ assert (importedType);
1437
+
1424
1438
if (importKind == ImportTypeKind::RecordField &&
1425
1439
importedType->isAnyClassReferenceType ()) {
1426
1440
// Wrap retainable struct fields in Unmanaged.
@@ -1435,10 +1449,10 @@ static ImportedType adjustTypeForConcreteImport(
1435
1449
// Wrap class, class protocol, function, and metatype types in an
1436
1450
// optional type.
1437
1451
bool isIUO = false ;
1438
- if (importKind != ImportTypeKind::Typedef && canImportAsOptional (hint)) {
1452
+ if (importKind != ImportTypeKind::Typedef && optKind != OTK_None &&
1453
+ canImportAsOptional (hint)) {
1439
1454
isIUO = optKind == OTK_ImplicitlyUnwrappedOptional;
1440
- if (optKind != OTK_None)
1441
- importedType = OptionalType::get (importedType);
1455
+ importedType = OptionalType::get (importedType);
1442
1456
}
1443
1457
1444
1458
return {importedType, isIUO};
0 commit comments