@@ -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;
@@ -1176,17 +1213,23 @@ NameImporter::considerAsyncImport(
1176
1213
StringRef baseName,
1177
1214
SmallVectorImpl<StringRef> ¶mNames,
1178
1215
ArrayRef<const clang::ParmVarDecl *> params,
1179
- bool isInitializer, bool hasCustomName ,
1216
+ bool isInitializer, CustomAsyncName customName ,
1180
1217
Optional<ForeignErrorConvention::Info> errorInfo) {
1181
1218
// If there are no unclaimed parameters, there's no .
1182
1219
unsigned errorParamAdjust = errorInfo ? 1 : 0 ;
1183
1220
if (params.size () - errorParamAdjust == 0 )
1184
1221
return None;
1185
1222
1223
+ // When there is a custom async name, it will have removed the completion
1224
+ // handler parameter already.
1225
+ unsigned customAsyncNameAdjust =
1226
+ customName == CustomAsyncName::SwiftAsyncName ? 1 : 0 ;
1227
+
1186
1228
// If the # of parameter names doesn't line up with the # of parameters,
1187
1229
// bail out. There are extra C parameters on the method or a custom name
1188
1230
// was incorrect.
1189
- if (params.size () != paramNames.size () + errorParamAdjust)
1231
+ if (params.size () !=
1232
+ paramNames.size () + errorParamAdjust + customAsyncNameAdjust)
1190
1233
return None;
1191
1234
1192
1235
// The last parameter will be the completion handler for an async function.
@@ -1195,20 +1238,37 @@ NameImporter::considerAsyncImport(
1195
1238
1196
1239
// Determine whether the naming indicates that this is a completion
1197
1240
// handler.
1198
- if (isCompletionHandlerParamName (
1199
- paramNames[completionHandlerParamNameIndex]) ||
1200
- (completionHandlerParamNameIndex > 0 &&
1201
- stripWithCompletionHandlerSuffix (
1202
- paramNames[completionHandlerParamNameIndex]))) {
1203
- // The argument label itself has an appropriate name.
1204
- } else if (!hasCustomName && completionHandlerParamIndex == 0 &&
1205
- stripWithCompletionHandlerSuffix (baseName)) {
1206
- // The base name implies that the first parameter is a completion handler.
1207
- } else if (isCompletionHandlerParamName (
1208
- params[completionHandlerParamIndex]->getName ())) {
1209
- // The parameter has an appropriate name.
1210
- } else {
1241
+ switch (customName) {
1242
+ case CustomAsyncName::None:
1243
+ // Check whether the first parameter is the completion handler and the
1244
+ // base name has a suitable completion-handler suffix.
1245
+ if (completionHandlerParamIndex == 0 &&
1246
+ stripWithCompletionHandlerSuffix (baseName))
1247
+ break ;
1248
+
1249
+ LLVM_FALLTHROUGH;
1250
+
1251
+ case CustomAsyncName::SwiftName:
1252
+ // Check whether the argument label itself has an appropriate name.
1253
+ if (isCompletionHandlerParamName (
1254
+ paramNames[completionHandlerParamNameIndex]) ||
1255
+ (completionHandlerParamNameIndex > 0 &&
1256
+ stripWithCompletionHandlerSuffix (
1257
+ paramNames[completionHandlerParamNameIndex]))) {
1258
+ break ;
1259
+ }
1260
+
1261
+ // Check whether the parameter itself has a name that indicates that
1262
+ // it is a completion handelr.
1263
+ if (isCompletionHandlerParamName (
1264
+ params[completionHandlerParamIndex]->getName ()))
1265
+ break ;
1266
+
1211
1267
return None;
1268
+
1269
+ case CustomAsyncName::SwiftAsyncName:
1270
+ // Having a custom async name implies that this is a completion handler.
1271
+ break ;
1212
1272
}
1213
1273
1214
1274
// Used for returns once we've determined that the method cannot be
@@ -1288,8 +1348,16 @@ NameImporter::considerAsyncImport(
1288
1348
break ;
1289
1349
}
1290
1350
1291
- // Drop the completion handler parameter name.
1292
- paramNames.erase (paramNames.begin () + completionHandlerParamNameIndex);
1351
+ // Drop the completion handler parameter name when needed.
1352
+ switch (customName) {
1353
+ case CustomAsyncName::None:
1354
+ case CustomAsyncName::SwiftName:
1355
+ paramNames.erase (paramNames.begin () + completionHandlerParamNameIndex);
1356
+ break ;
1357
+
1358
+ case CustomAsyncName::SwiftAsyncName:
1359
+ break ;
1360
+ }
1293
1361
1294
1362
return ForeignAsyncConvention::Info (
1295
1363
completionHandlerParamIndex, completionHandlerErrorParamIndex);
@@ -1453,11 +1521,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1453
1521
}
1454
1522
1455
1523
// If we have a swift_name attribute, use that.
1456
- if (auto * nameAttr = findSwiftNameAttr (D, version)) {
1524
+ if (auto nameAttr = findSwiftNameAttr (D, version)) {
1457
1525
bool skipCustomName = false ;
1458
1526
1459
1527
// Parse the name.
1460
- ParsedDeclName parsedName = parseDeclName (nameAttr->getName () );
1528
+ ParsedDeclName parsedName = parseDeclName (nameAttr->name );
1461
1529
if (!parsedName || parsedName.isOperator ())
1462
1530
return result;
1463
1531
@@ -1532,7 +1600,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1532
1600
if (version.supportsConcurrency ()) {
1533
1601
if (auto asyncInfo = considerAsyncImport (
1534
1602
method, parsedName.BaseName , parsedName.ArgumentLabels ,
1535
- params, isInitializer, /* hasCustomName=*/ true ,
1603
+ params, isInitializer,
1604
+ nameAttr->isAsync ? CustomAsyncName::SwiftAsyncName
1605
+ : CustomAsyncName::SwiftName,
1536
1606
result.getErrorInfo ())) {
1537
1607
result.info .hasAsyncInfo = true ;
1538
1608
result.info .asyncInfo = *asyncInfo;
@@ -1541,6 +1611,10 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1541
1611
result.declName = formDeclName (
1542
1612
swiftCtx, parsedName.BaseName , parsedName.ArgumentLabels ,
1543
1613
/* isFunction=*/ true , isInitializer);
1614
+ } else if (nameAttr->isAsync ) {
1615
+ // The custom name was for an async import, but we didn't in fact
1616
+ // import as async for some reason. Ignore this import.
1617
+ return ImportedName ();
1544
1618
}
1545
1619
}
1546
1620
}
@@ -1816,7 +1890,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
1816
1890
result.info .accessorKind == ImportedAccessorKind::None) {
1817
1891
if (auto asyncInfo = considerAsyncImport (
1818
1892
objcMethod, baseName, argumentNames, params, isInitializer,
1819
- /* hasCustomName= */ false , result.getErrorInfo ())) {
1893
+ CustomAsyncName::None , result.getErrorInfo ())) {
1820
1894
result.info .hasAsyncInfo = true ;
1821
1895
result.info .asyncInfo = *asyncInfo;
1822
1896
}
0 commit comments