@@ -539,12 +539,26 @@ determineFactoryInitializerKind(const clang::ObjCMethodDecl *method) {
539
539
}
540
540
541
541
namespace {
542
+ // / Describes the details of any swift_name or swift_async_name
543
+ // / attribute found via
544
+ struct AnySwiftNameAttr {
545
+ // / The name itself.
546
+ StringRef name;
547
+
548
+ // / Whether this was a swift_async_name attribute.
549
+ bool isAsync;
550
+
551
+ friend bool operator ==(AnySwiftNameAttr lhs, AnySwiftNameAttr rhs) {
552
+ return lhs.name == rhs.name && lhs.isAsync == rhs.isAsync ;
553
+ }
554
+ };
555
+
542
556
// / Aggregate struct for the common members of clang::SwiftVersionedAttr and
543
557
// / clang::SwiftVersionedRemovalAttr.
544
558
// /
545
559
// / For a SwiftVersionedRemovalAttr, the Attr member will be null.
546
560
struct VersionedSwiftNameInfo {
547
- const clang::SwiftNameAttr * Attr;
561
+ Optional<AnySwiftNameAttr> Attr;
548
562
llvm::VersionTuple Version;
549
563
bool IsReplacedByActive;
550
564
};
@@ -594,8 +608,7 @@ checkVersionedSwiftName(VersionedSwiftNameInfo info,
594
608
return VersionedSwiftNameAction::Use;
595
609
}
596
610
597
-
598
- static const clang::SwiftNameAttr *
611
+ static Optional<AnySwiftNameAttr>
599
612
findSwiftNameAttr (const clang::Decl *decl, ImportNameVersion version) {
600
613
#ifndef NDEBUG
601
614
if (Optional<const clang::Decl *> def = getDefinitionForClangTypeDecl (decl)) {
@@ -605,7 +618,24 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
605
618
#endif
606
619
607
620
if (version == ImportNameVersion::raw ())
608
- return nullptr ;
621
+ return None;
622
+
623
+ // / Decode the given Clang attribute to try to determine whether it is
624
+ // / a Swift name attribute.
625
+ auto decodeAttr =
626
+ [&](const clang::Attr *attr) -> Optional<AnySwiftNameAttr> {
627
+ if (version.supportsConcurrency ()) {
628
+ if (auto asyncAttr = dyn_cast<clang::SwiftAsyncNameAttr>(attr)) {
629
+ return AnySwiftNameAttr { asyncAttr->getName (), /* isAsync=*/ true };
630
+ }
631
+ }
632
+
633
+ if (auto nameAttr = dyn_cast<clang::SwiftNameAttr>(attr)) {
634
+ return AnySwiftNameAttr { nameAttr->getName (), /* isAsync=*/ false };
635
+ }
636
+
637
+ return None;
638
+ };
609
639
610
640
// Handle versioned API notes for Swift 3 and later. This is the common case.
611
641
if (version > ImportNameVersion::swift2 ()) {
@@ -615,15 +645,22 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
615
645
if (importer::isSpecialUIKitStructZeroProperty (namedDecl))
616
646
version = ImportNameVersion::swift4_2 ();
617
647
618
- const auto *activeAttr = decl->getAttr <clang::SwiftNameAttr>();
619
- const clang::SwiftNameAttr *result = activeAttr;
648
+ // Dig out the attribute that specifies the Swift name.
649
+ Optional<AnySwiftNameAttr> activeAttr;
650
+ if (auto asyncAttr = decl->getAttr <clang::SwiftAsyncNameAttr>())
651
+ activeAttr = decodeAttr (asyncAttr);
652
+ if (!activeAttr) {
653
+ if (auto nameAttr = decl->getAttr <clang::SwiftNameAttr>())
654
+ activeAttr = decodeAttr (nameAttr);
655
+ }
656
+
657
+ Optional<AnySwiftNameAttr> result = activeAttr;
620
658
llvm::VersionTuple bestSoFar;
621
659
for (auto *attr : decl->attrs ()) {
622
660
VersionedSwiftNameInfo info;
623
661
624
662
if (auto *versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr)) {
625
- auto *added =
626
- dyn_cast<clang::SwiftNameAttr>(versionedAttr->getAttrToAdd ());
663
+ auto added = decodeAttr (versionedAttr->getAttrToAdd ());
627
664
if (!added)
628
665
continue ;
629
666
@@ -634,7 +671,7 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
634
671
dyn_cast<clang::SwiftVersionedRemovalAttr>(attr)) {
635
672
if (removeAttr->getAttrKindToRemove () != clang::attr::SwiftName)
636
673
continue ;
637
- info = {nullptr , removeAttr->getVersion (),
674
+ info = {None , removeAttr->getVersion (),
638
675
removeAttr->getIsReplacedByActive ()};
639
676
640
677
} else {
@@ -673,11 +710,11 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
673
710
// The remainder of this function emulates the limited form of swift_name
674
711
// supported in Swift 2.
675
712
auto attr = decl->getAttr <clang::SwiftNameAttr>();
676
- if (!attr) return nullptr ;
713
+ if (!attr) return None ;
677
714
678
715
// API notes produce attributes with no source location; ignore them because
679
716
// they weren't used for naming in Swift 2.
680
- if (attr->getLocation ().isInvalid ()) return nullptr ;
717
+ if (attr->getLocation ().isInvalid ()) return None ;
681
718
682
719
// Hardcode certain kinds of explicitly-written Swift names that were
683
720
// permitted and used in Swift 2. All others are ignored, so that we are
@@ -686,28 +723,28 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
686
723
if (auto enumerator = dyn_cast<clang::EnumConstantDecl>(decl)) {
687
724
// Foundation's NSXMLDTDKind had an explicit swift_name attribute in
688
725
// Swift 2. Honor it.
689
- if (enumerator->getName () == " NSXMLDTDKind" ) return attr;
690
- return nullptr ;
726
+ if (enumerator->getName () == " NSXMLDTDKind" ) return decodeAttr ( attr) ;
727
+ return None ;
691
728
}
692
729
693
730
if (auto method = dyn_cast<clang::ObjCMethodDecl>(decl)) {
694
731
// Special case: mapping to an initializer.
695
732
if (attr->getName ().startswith (" init(" )) {
696
733
// If we have a class method, honor the annotation to turn a class
697
734
// method into an initializer.
698
- if (method->isClassMethod ()) return attr;
735
+ if (method->isClassMethod ()) return decodeAttr ( attr) ;
699
736
700
- return nullptr ;
737
+ return None ;
701
738
}
702
739
703
740
// Special case: preventing a mapping to an initializer.
704
741
if (matchFactoryAsInitName (method) && determineFactoryInitializerKind (method))
705
- return attr;
742
+ return decodeAttr ( attr) ;
706
743
707
- return nullptr ;
744
+ return None ;
708
745
}
709
746
710
- return nullptr ;
747
+ return None ;
711
748
}
712
749
713
750
// / Determine whether the given class method should be imported as
@@ -716,8 +753,8 @@ static FactoryAsInitKind
716
753
getFactoryAsInit (const clang::ObjCInterfaceDecl *classDecl,
717
754
const clang::ObjCMethodDecl *method,
718
755
ImportNameVersion version) {
719
- if (auto * customNameAttr = findSwiftNameAttr (method, version)) {
720
- if (customNameAttr->getName () .startswith (" init(" ))
756
+ if (auto customNameAttr = findSwiftNameAttr (method, version)) {
757
+ if (customNameAttr->name .startswith (" init(" ))
721
758
return FactoryAsInitKind::AsInitializer;
722
759
else
723
760
return FactoryAsInitKind::AsClassMethod;
@@ -1172,17 +1209,23 @@ NameImporter::considerAsyncImport(
1172
1209
StringRef baseName,
1173
1210
SmallVectorImpl<StringRef> ¶mNames,
1174
1211
ArrayRef<const clang::ParmVarDecl *> params,
1175
- bool isInitializer, bool hasCustomName ,
1212
+ bool isInitializer, CustomAsyncName customName ,
1176
1213
Optional<ForeignErrorConvention::Info> errorInfo) {
1177
1214
// If there are no unclaimed parameters, there's no .
1178
1215
unsigned errorParamAdjust = errorInfo ? 1 : 0 ;
1179
1216
if (params.size () - errorParamAdjust == 0 )
1180
1217
return None;
1181
1218
1219
+ // When there is a custom async name, it will have removed the completion
1220
+ // handler parameter already.
1221
+ unsigned customAsyncNameAdjust =
1222
+ customName == CustomAsyncName::SwiftAsyncName ? 1 : 0 ;
1223
+
1182
1224
// If the # of parameter names doesn't line up with the # of parameters,
1183
1225
// bail out. There are extra C parameters on the method or a custom name
1184
1226
// was incorrect.
1185
- if (params.size () != paramNames.size () + errorParamAdjust)
1227
+ if (params.size () !=
1228
+ paramNames.size () + errorParamAdjust + customAsyncNameAdjust)
1186
1229
return None;
1187
1230
1188
1231
// The last parameter will be the completion handler for an async function.
@@ -1191,20 +1234,37 @@ NameImporter::considerAsyncImport(
1191
1234
1192
1235
// Determine whether the naming indicates that this is a completion
1193
1236
// handler.
1194
- if (isCompletionHandlerParamName (
1195
- paramNames[completionHandlerParamNameIndex]) ||
1196
- (completionHandlerParamNameIndex > 0 &&
1197
- stripWithCompletionHandlerSuffix (
1198
- paramNames[completionHandlerParamNameIndex]))) {
1199
- // The argument label itself has an appropriate name.
1200
- } else if (!hasCustomName && completionHandlerParamIndex == 0 &&
1201
- stripWithCompletionHandlerSuffix (baseName)) {
1202
- // The base name implies that the first parameter is a completion handler.
1203
- } else if (isCompletionHandlerParamName (
1204
- params[completionHandlerParamIndex]->getName ())) {
1205
- // The parameter has an appropriate name.
1206
- } else {
1237
+ switch (customName) {
1238
+ case CustomAsyncName::None:
1239
+ // Check whether the first parameter is the completion handler and the
1240
+ // base name has a suitable completion-handler suffix.
1241
+ if (completionHandlerParamIndex == 0 &&
1242
+ stripWithCompletionHandlerSuffix (baseName))
1243
+ break ;
1244
+
1245
+ LLVM_FALLTHROUGH;
1246
+
1247
+ case CustomAsyncName::SwiftName:
1248
+ // Check whether the argument label itself has an appropriate name.
1249
+ if (isCompletionHandlerParamName (
1250
+ paramNames[completionHandlerParamNameIndex]) ||
1251
+ (completionHandlerParamNameIndex > 0 &&
1252
+ stripWithCompletionHandlerSuffix (
1253
+ paramNames[completionHandlerParamNameIndex]))) {
1254
+ break ;
1255
+ }
1256
+
1257
+ // Check whether the parameter itself has a name that indicates that
1258
+ // it is a completion handelr.
1259
+ if (isCompletionHandlerParamName (
1260
+ params[completionHandlerParamIndex]->getName ()))
1261
+ break ;
1262
+
1207
1263
return None;
1264
+
1265
+ case CustomAsyncName::SwiftAsyncName:
1266
+ // Having a custom async name implies that this is a completion handler.
1267
+ break ;
1208
1268
}
1209
1269
1210
1270
// Used for returns once we've determined that the method cannot be
@@ -1284,8 +1344,16 @@ NameImporter::considerAsyncImport(
1284
1344
break ;
1285
1345
}
1286
1346
1287
- // Drop the completion handler parameter name.
1288
- paramNames.erase (paramNames.begin () + completionHandlerParamNameIndex);
1347
+ // Drop the completion handler parameter name when needed.
1348
+ switch (customName) {
1349
+ case CustomAsyncName::None:
1350
+ case CustomAsyncName::SwiftName:
1351
+ paramNames.erase (paramNames.begin () + completionHandlerParamNameIndex);
1352
+ break ;
1353
+
1354
+ case CustomAsyncName::SwiftAsyncName:
1355
+ break ;
1356
+ }
1289
1357
1290
1358
return ForeignAsyncConvention::Info (
1291
1359
completionHandlerParamIndex, completionHandlerErrorParamIndex);
@@ -1449,11 +1517,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1449
1517
}
1450
1518
1451
1519
// If we have a swift_name attribute, use that.
1452
- if (auto * nameAttr = findSwiftNameAttr (D, version)) {
1520
+ if (auto nameAttr = findSwiftNameAttr (D, version)) {
1453
1521
bool skipCustomName = false ;
1454
1522
1455
1523
// Parse the name.
1456
- ParsedDeclName parsedName = parseDeclName (nameAttr->getName () );
1524
+ ParsedDeclName parsedName = parseDeclName (nameAttr->name );
1457
1525
if (!parsedName || parsedName.isOperator ())
1458
1526
return result;
1459
1527
@@ -1528,7 +1596,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1528
1596
if (version.supportsConcurrency ()) {
1529
1597
if (auto asyncInfo = considerAsyncImport (
1530
1598
method, parsedName.BaseName , parsedName.ArgumentLabels ,
1531
- params, isInitializer, /* hasCustomName=*/ true ,
1599
+ params, isInitializer,
1600
+ nameAttr->isAsync ? CustomAsyncName::SwiftAsyncName
1601
+ : CustomAsyncName::SwiftName,
1532
1602
result.getErrorInfo ())) {
1533
1603
result.info .hasAsyncInfo = true ;
1534
1604
result.info .asyncInfo = *asyncInfo;
@@ -1537,6 +1607,10 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1537
1607
result.declName = formDeclName (
1538
1608
swiftCtx, parsedName.BaseName , parsedName.ArgumentLabels ,
1539
1609
/* isFunction=*/ true , isInitializer);
1610
+ } else if (nameAttr->isAsync ) {
1611
+ // The custom name was for an async import, but we didn't in fact
1612
+ // import as async for some reason. Ignore this import.
1613
+ return ImportedName ();
1540
1614
}
1541
1615
}
1542
1616
}
@@ -1812,7 +1886,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1812
1886
result.info .accessorKind == ImportedAccessorKind::None) {
1813
1887
if (auto asyncInfo = considerAsyncImport (
1814
1888
objcMethod, baseName, argumentNames, params, isInitializer,
1815
- /* hasCustomName= */ false , result.getErrorInfo ())) {
1889
+ CustomAsyncName::None , result.getErrorInfo ())) {
1816
1890
result.info .hasAsyncInfo = true ;
1817
1891
result.info .asyncInfo = *asyncInfo;
1818
1892
}
0 commit comments