@@ -539,12 +539,26 @@ determineFactoryInitializerKind(const clang::ObjCMethodDecl *method) {
539539}
540540
541541namespace {
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+
542556// / Aggregate struct for the common members of clang::SwiftVersionedAttr and
543557// / clang::SwiftVersionedRemovalAttr.
544558// /
545559// / For a SwiftVersionedRemovalAttr, the Attr member will be null.
546560struct VersionedSwiftNameInfo {
547- const clang::SwiftNameAttr * Attr;
561+ Optional<AnySwiftNameAttr> Attr;
548562 llvm::VersionTuple Version;
549563 bool IsReplacedByActive;
550564};
@@ -594,8 +608,7 @@ checkVersionedSwiftName(VersionedSwiftNameInfo info,
594608 return VersionedSwiftNameAction::Use;
595609}
596610
597-
598- static const clang::SwiftNameAttr *
611+ static Optional<AnySwiftNameAttr>
599612findSwiftNameAttr (const clang::Decl *decl, ImportNameVersion version) {
600613#ifndef NDEBUG
601614 if (Optional<const clang::Decl *> def = getDefinitionForClangTypeDecl (decl)) {
@@ -605,7 +618,24 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
605618#endif
606619
607620 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+ };
609639
610640 // Handle versioned API notes for Swift 3 and later. This is the common case.
611641 if (version > ImportNameVersion::swift2 ()) {
@@ -615,15 +645,22 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
615645 if (importer::isSpecialUIKitStructZeroProperty (namedDecl))
616646 version = ImportNameVersion::swift4_2 ();
617647
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;
620658 llvm::VersionTuple bestSoFar;
621659 for (auto *attr : decl->attrs ()) {
622660 VersionedSwiftNameInfo info;
623661
624662 if (auto *versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr)) {
625- auto *added =
626- dyn_cast<clang::SwiftNameAttr>(versionedAttr->getAttrToAdd ());
663+ auto added = decodeAttr (versionedAttr->getAttrToAdd ());
627664 if (!added)
628665 continue ;
629666
@@ -634,7 +671,7 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
634671 dyn_cast<clang::SwiftVersionedRemovalAttr>(attr)) {
635672 if (removeAttr->getAttrKindToRemove () != clang::attr::SwiftName)
636673 continue ;
637- info = {nullptr , removeAttr->getVersion (),
674+ info = {None , removeAttr->getVersion (),
638675 removeAttr->getIsReplacedByActive ()};
639676
640677 } else {
@@ -673,11 +710,11 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
673710 // The remainder of this function emulates the limited form of swift_name
674711 // supported in Swift 2.
675712 auto attr = decl->getAttr <clang::SwiftNameAttr>();
676- if (!attr) return nullptr ;
713+ if (!attr) return None ;
677714
678715 // API notes produce attributes with no source location; ignore them because
679716 // they weren't used for naming in Swift 2.
680- if (attr->getLocation ().isInvalid ()) return nullptr ;
717+ if (attr->getLocation ().isInvalid ()) return None ;
681718
682719 // Hardcode certain kinds of explicitly-written Swift names that were
683720 // 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) {
686723 if (auto enumerator = dyn_cast<clang::EnumConstantDecl>(decl)) {
687724 // Foundation's NSXMLDTDKind had an explicit swift_name attribute in
688725 // 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 ;
691728 }
692729
693730 if (auto method = dyn_cast<clang::ObjCMethodDecl>(decl)) {
694731 // Special case: mapping to an initializer.
695732 if (attr->getName ().startswith (" init(" )) {
696733 // If we have a class method, honor the annotation to turn a class
697734 // method into an initializer.
698- if (method->isClassMethod ()) return attr;
735+ if (method->isClassMethod ()) return decodeAttr ( attr) ;
699736
700- return nullptr ;
737+ return None ;
701738 }
702739
703740 // Special case: preventing a mapping to an initializer.
704741 if (matchFactoryAsInitName (method) && determineFactoryInitializerKind (method))
705- return attr;
742+ return decodeAttr ( attr) ;
706743
707- return nullptr ;
744+ return None ;
708745 }
709746
710- return nullptr ;
747+ return None ;
711748}
712749
713750// / Determine whether the given class method should be imported as
@@ -716,8 +753,8 @@ static FactoryAsInitKind
716753getFactoryAsInit (const clang::ObjCInterfaceDecl *classDecl,
717754 const clang::ObjCMethodDecl *method,
718755 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(" ))
721758 return FactoryAsInitKind::AsInitializer;
722759 else
723760 return FactoryAsInitKind::AsClassMethod;
@@ -1172,17 +1209,23 @@ NameImporter::considerAsyncImport(
11721209 StringRef baseName,
11731210 SmallVectorImpl<StringRef> ¶mNames,
11741211 ArrayRef<const clang::ParmVarDecl *> params,
1175- bool isInitializer, bool hasCustomName ,
1212+ bool isInitializer, CustomAsyncName customName ,
11761213 Optional<ForeignErrorConvention::Info> errorInfo) {
11771214 // If there are no unclaimed parameters, there's no .
11781215 unsigned errorParamAdjust = errorInfo ? 1 : 0 ;
11791216 if (params.size () - errorParamAdjust == 0 )
11801217 return None;
11811218
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+
11821224 // If the # of parameter names doesn't line up with the # of parameters,
11831225 // bail out. There are extra C parameters on the method or a custom name
11841226 // was incorrect.
1185- if (params.size () != paramNames.size () + errorParamAdjust)
1227+ if (params.size () !=
1228+ paramNames.size () + errorParamAdjust + customAsyncNameAdjust)
11861229 return None;
11871230
11881231 // The last parameter will be the completion handler for an async function.
@@ -1191,20 +1234,37 @@ NameImporter::considerAsyncImport(
11911234
11921235 // Determine whether the naming indicates that this is a completion
11931236 // 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+
12071263 return None;
1264+
1265+ case CustomAsyncName::SwiftAsyncName:
1266+ // Having a custom async name implies that this is a completion handler.
1267+ break ;
12081268 }
12091269
12101270 // Used for returns once we've determined that the method cannot be
@@ -1284,8 +1344,16 @@ NameImporter::considerAsyncImport(
12841344 break ;
12851345 }
12861346
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+ }
12891357
12901358 return ForeignAsyncConvention::Info (
12911359 completionHandlerParamIndex, completionHandlerErrorParamIndex);
@@ -1449,11 +1517,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14491517 }
14501518
14511519 // If we have a swift_name attribute, use that.
1452- if (auto * nameAttr = findSwiftNameAttr (D, version)) {
1520+ if (auto nameAttr = findSwiftNameAttr (D, version)) {
14531521 bool skipCustomName = false ;
14541522
14551523 // Parse the name.
1456- ParsedDeclName parsedName = parseDeclName (nameAttr->getName () );
1524+ ParsedDeclName parsedName = parseDeclName (nameAttr->name );
14571525 if (!parsedName || parsedName.isOperator ())
14581526 return result;
14591527
@@ -1528,7 +1596,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
15281596 if (version.supportsConcurrency ()) {
15291597 if (auto asyncInfo = considerAsyncImport (
15301598 method, parsedName.BaseName , parsedName.ArgumentLabels ,
1531- params, isInitializer, /* hasCustomName=*/ true ,
1599+ params, isInitializer,
1600+ nameAttr->isAsync ? CustomAsyncName::SwiftAsyncName
1601+ : CustomAsyncName::SwiftName,
15321602 result.getErrorInfo ())) {
15331603 result.info .hasAsyncInfo = true ;
15341604 result.info .asyncInfo = *asyncInfo;
@@ -1537,6 +1607,10 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
15371607 result.declName = formDeclName (
15381608 swiftCtx, parsedName.BaseName , parsedName.ArgumentLabels ,
15391609 /* 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 ();
15401614 }
15411615 }
15421616 }
@@ -1812,7 +1886,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
18121886 result.info .accessorKind == ImportedAccessorKind::None) {
18131887 if (auto asyncInfo = considerAsyncImport (
18141888 objcMethod, baseName, argumentNames, params, isInitializer,
1815- /* hasCustomName= */ false , result.getErrorInfo ())) {
1889+ CustomAsyncName::None , result.getErrorInfo ())) {
18161890 result.info .hasAsyncInfo = true ;
18171891 result.info .asyncInfo = *asyncInfo;
18181892 }
0 commit comments