@@ -68,6 +68,20 @@ importer::nameVersionFromOptions(const LangOptions &langOpts) {
6868 }
6969}
7070
71+ unsigned importer::majorVersionNumberForNameVersion (ImportNameVersion version) {
72+ switch (version) {
73+ case ImportNameVersion::Raw:
74+ return 0 ;
75+ case ImportNameVersion::Swift2:
76+ return 2 ;
77+ case ImportNameVersion::Swift3:
78+ return 3 ;
79+ case ImportNameVersion::Swift4:
80+ return 4 ;
81+ }
82+ }
83+
84+
7185// / Determine whether the given Clang selector matches the given
7286// / selector pieces.
7387static bool isNonNullarySelector (clang::Selector selector,
@@ -560,12 +574,90 @@ determineCtorInitializerKind(const clang::ObjCMethodDecl *method) {
560574 return None;
561575}
562576
577+ template <typename A>
578+ static bool matchesVersion (A *versionedAttr, ImportNameVersion version) {
579+ clang::VersionTuple attrVersion = versionedAttr->getVersion ();
580+ if (attrVersion.empty ())
581+ return version == ImportNameVersion::LAST_VERSION;
582+ return attrVersion.getMajor () == majorVersionNumberForNameVersion (version);
583+ }
584+
585+ const clang::SwiftNameAttr *
586+ importer::findSwiftNameAttr (const clang::Decl *decl,
587+ ImportNameVersion version) {
588+ if (version == ImportNameVersion::Raw)
589+ return nullptr ;
590+
591+ // Handle versioned API notes for Swift 3 and later. This is the common case.
592+ if (version != ImportNameVersion::Swift2) {
593+ for (auto *attr : decl->attrs ()) {
594+ if (auto *versionedAttr = dyn_cast<clang::SwiftVersionedAttr>(attr)) {
595+ if (!matchesVersion (versionedAttr, version))
596+ continue ;
597+ if (auto *added =
598+ dyn_cast<clang::SwiftNameAttr>(versionedAttr->getAttrToAdd ())) {
599+ return added;
600+ }
601+ }
602+
603+ if (auto *removeAttr = dyn_cast<clang::SwiftVersionedRemovalAttr>(attr)) {
604+ if (!matchesVersion (removeAttr, version))
605+ continue ;
606+ if (removeAttr->getAttrKindToRemove () == clang::attr::SwiftName)
607+ return nullptr ;
608+ }
609+ }
610+
611+ return decl->getAttr <clang::SwiftNameAttr>();
612+ }
613+
614+ // The remainder of this function emulates the limited form of swift_name
615+ // supported in Swift 2.
616+ auto attr = decl->getAttr <clang::SwiftNameAttr>();
617+ if (!attr) return nullptr ;
618+
619+ // API notes produce implicit attributes; ignore them because they weren't
620+ // used for naming in Swift 2.
621+ if (attr->isImplicit ()) return nullptr ;
622+
623+ // Whitelist certain explicitly-written Swift names that were
624+ // permitted and used in Swift 2. All others are ignored, so that we are
625+ // assuming a more direct translation from the Objective-C APIs into Swift.
626+
627+ if (auto enumerator = dyn_cast<clang::EnumConstantDecl>(decl)) {
628+ // Foundation's NSXMLDTDKind had an explicit swift_name attribute in
629+ // Swift 2. Honor it.
630+ if (enumerator->getName () == " NSXMLDTDKind" ) return attr;
631+ return nullptr ;
632+ }
633+
634+ if (auto method = dyn_cast<clang::ObjCMethodDecl>(decl)) {
635+ // Special case: mapping to an initializer.
636+ if (attr->getName ().startswith (" init(" )) {
637+ // If we have a class method, honor the annotation to turn a class
638+ // method into an initializer.
639+ if (method->isClassMethod ()) return attr;
640+
641+ return nullptr ;
642+ }
643+
644+ // Special case: preventing a mapping to an initializer.
645+ if (matchFactoryAsInitName (method) && determineCtorInitializerKind (method))
646+ return attr;
647+
648+ return nullptr ;
649+ }
650+
651+ return nullptr ;
652+ }
653+
563654// / Determine whether the given class method should be imported as
564655// / an initializer.
565656static FactoryAsInitKind
566657getFactoryAsInit (const clang::ObjCInterfaceDecl *classDecl,
567- const clang::ObjCMethodDecl *method) {
568- if (auto *customNameAttr = method->getAttr <clang::SwiftNameAttr>()) {
658+ const clang::ObjCMethodDecl *method,
659+ ImportNameVersion version) {
660+ if (auto *customNameAttr = findSwiftNameAttr (method, version)) {
569661 if (customNameAttr->getName ().startswith (" init(" ))
570662 return FactoryAsInitKind::AsInitializer;
571663 else
@@ -586,6 +678,7 @@ getFactoryAsInit(const clang::ObjCInterfaceDecl *classDecl,
586678// / imported. Note that this does not distinguish designated
587679// / vs. convenience; both will be classified as "designated".
588680static bool shouldImportAsInitializer (const clang::ObjCMethodDecl *method,
681+ ImportNameVersion version,
589682 unsigned &prefixLength,
590683 CtorInitializerKind &kind) {
591684 // / Is this an initializer?
@@ -604,7 +697,7 @@ static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
604697
605698 // Check whether we should try to import this factory method as an
606699 // initializer.
607- switch (getFactoryAsInit (objcClass, method)) {
700+ switch (getFactoryAsInit (objcClass, method, version )) {
608701 case FactoryAsInitKind::AsInitializer:
609702 // Okay; check for the correct result type below.
610703 prefixLength = 0 ;
@@ -634,55 +727,6 @@ static bool shouldImportAsInitializer(const clang::ObjCMethodDecl *method,
634727 return false ;
635728}
636729
637- // / Find the swift_name attribute associated with this declaration, if
638- // / any.
639- // /
640- // / \param version The version we're importing the name as
641- static clang::SwiftNameAttr *findSwiftNameAttr (const clang::Decl *decl,
642- ImportNameVersion version) {
643- // Find the attribute.
644- auto attr = decl->getAttr <clang::SwiftNameAttr>();
645- if (!attr) return nullptr ;
646-
647- // If we're not emulating the Swift 2 behavior, return what we got.
648- if (version != ImportNameVersion::Swift2)
649- return attr;
650-
651- // API notes produce implicit attributes; ignore them because they weren't
652- // used for naming in Swift 2.
653- if (attr->isImplicit ()) return nullptr ;
654-
655- // Whitelist certain explicitly-written Swift names that were
656- // permitted and used in Swift 2. All others are ignored, so that we are
657- // assuming a more direct translation from the Objective-C APIs into Swift.
658-
659- if (auto enumerator = dyn_cast<clang::EnumConstantDecl>(decl)) {
660- // Foundation's NSXMLDTDKind had an explicit swift_name attribute in
661- // Swift 2. Honor it.
662- if (enumerator->getName () == " NSXMLDTDKind" ) return attr;
663- return nullptr ;
664- }
665-
666- if (auto method = dyn_cast<clang::ObjCMethodDecl>(decl)) {
667- // Special case: mapping to an initializer.
668- if (attr->getName ().startswith (" init(" )) {
669- // If we have a class method, honor the annotation to turn a class
670- // method into an initializer.
671- if (method->isClassMethod ()) return attr;
672-
673- return nullptr ;
674- }
675-
676- // Special case: preventing a mapping to an initializer.
677- if (matchFactoryAsInitName (method) && determineCtorInitializerKind (method))
678- return attr;
679-
680- return nullptr ;
681- }
682-
683- return nullptr ;
684- }
685-
686730// / Attempt to omit needless words from the given function name.
687731static bool omitNeedlessWordsInFunctionName (
688732 StringRef &baseName, SmallVectorImpl<StringRef> &argumentNames,
@@ -1179,7 +1223,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
11791223 if (method) {
11801224 unsigned initPrefixLength;
11811225 if (parsedName.BaseName == " init" && parsedName.IsFunctionName ) {
1182- if (!shouldImportAsInitializer (method, initPrefixLength,
1226+ if (!shouldImportAsInitializer (method, version, initPrefixLength,
11831227 result.info .initKind )) {
11841228 // We cannot import this as an initializer anyway.
11851229 return ImportedName ();
@@ -1354,7 +1398,8 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
13541398 if (baseName.empty ())
13551399 return ImportedName ();
13561400
1357- isInitializer = shouldImportAsInitializer (objcMethod, initializerPrefixLen,
1401+ isInitializer = shouldImportAsInitializer (objcMethod, version,
1402+ initializerPrefixLen,
13581403 result.info .initKind );
13591404
13601405 // If we would import a factory method as an initializer but were
0 commit comments