@@ -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;
@@ -1176,17 +1213,23 @@ NameImporter::considerAsyncImport(
11761213 StringRef baseName,
11771214 SmallVectorImpl<StringRef> ¶mNames,
11781215 ArrayRef<const clang::ParmVarDecl *> params,
1179- bool isInitializer, bool hasCustomName ,
1216+ bool isInitializer, CustomAsyncName customName ,
11801217 Optional<ForeignErrorConvention::Info> errorInfo) {
11811218 // If there are no unclaimed parameters, there's no .
11821219 unsigned errorParamAdjust = errorInfo ? 1 : 0 ;
11831220 if (params.size () - errorParamAdjust == 0 )
11841221 return None;
11851222
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+
11861228 // If the # of parameter names doesn't line up with the # of parameters,
11871229 // bail out. There are extra C parameters on the method or a custom name
11881230 // was incorrect.
1189- if (params.size () != paramNames.size () + errorParamAdjust)
1231+ if (params.size () !=
1232+ paramNames.size () + errorParamAdjust + customAsyncNameAdjust)
11901233 return None;
11911234
11921235 // The last parameter will be the completion handler for an async function.
@@ -1195,20 +1238,37 @@ NameImporter::considerAsyncImport(
11951238
11961239 // Determine whether the naming indicates that this is a completion
11971240 // 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+
12111267 return None;
1268+
1269+ case CustomAsyncName::SwiftAsyncName:
1270+ // Having a custom async name implies that this is a completion handler.
1271+ break ;
12121272 }
12131273
12141274 // Used for returns once we've determined that the method cannot be
@@ -1288,8 +1348,16 @@ NameImporter::considerAsyncImport(
12881348 break ;
12891349 }
12901350
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+ }
12931361
12941362 return ForeignAsyncConvention::Info (
12951363 completionHandlerParamIndex, completionHandlerErrorParamIndex);
@@ -1453,11 +1521,11 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
14531521 }
14541522
14551523 // If we have a swift_name attribute, use that.
1456- if (auto * nameAttr = findSwiftNameAttr (D, version)) {
1524+ if (auto nameAttr = findSwiftNameAttr (D, version)) {
14571525 bool skipCustomName = false ;
14581526
14591527 // Parse the name.
1460- ParsedDeclName parsedName = parseDeclName (nameAttr->getName () );
1528+ ParsedDeclName parsedName = parseDeclName (nameAttr->name );
14611529 if (!parsedName || parsedName.isOperator ())
14621530 return result;
14631531
@@ -1532,7 +1600,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
15321600 if (version.supportsConcurrency ()) {
15331601 if (auto asyncInfo = considerAsyncImport (
15341602 method, parsedName.BaseName , parsedName.ArgumentLabels ,
1535- params, isInitializer, /* hasCustomName=*/ true ,
1603+ params, isInitializer,
1604+ nameAttr->isAsync ? CustomAsyncName::SwiftAsyncName
1605+ : CustomAsyncName::SwiftName,
15361606 result.getErrorInfo ())) {
15371607 result.info .hasAsyncInfo = true ;
15381608 result.info .asyncInfo = *asyncInfo;
@@ -1541,6 +1611,10 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
15411611 result.declName = formDeclName (
15421612 swiftCtx, parsedName.BaseName , parsedName.ArgumentLabels ,
15431613 /* 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 ();
15441618 }
15451619 }
15461620 }
@@ -1816,7 +1890,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
18161890 result.info .accessorKind == ImportedAccessorKind::None) {
18171891 if (auto asyncInfo = considerAsyncImport (
18181892 objcMethod, baseName, argumentNames, params, isInitializer,
1819- /* hasCustomName= */ false , result.getErrorInfo ())) {
1893+ CustomAsyncName::None , result.getErrorInfo ())) {
18201894 result.info .hasAsyncInfo = true ;
18211895 result.info .asyncInfo = *asyncInfo;
18221896 }
0 commit comments