diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 8f59b79c6b18c..91eab4bc71ae2 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -8680,6 +8680,26 @@ bool importer::isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl) { return ident->isStr("UIEdgeInsetsZero") || ident->isStr("UIOffsetZero"); } +bool importer::isSpecialAppKitFunctionKeyProperty( + const clang::NamedDecl *decl) { + auto constant = dyn_cast(decl); + if (!constant) + return false; + + auto module = constant->getOwningModule(); + if (!module || module->getTopLevelModuleName() != "AppKit") + return false; + + clang::DeclarationName name = constant->getDeclName(); + const clang::IdentifierInfo *ident = name.getAsIdentifierInfo(); + if (!ident) + return false; + auto rawName = ident->getName(); + + return rawName.starts_with("NS") && + (rawName.ends_with("FunctionKey") || rawName.ends_with("Character")); +} + bool importer::hasSameUnderlyingType(const clang::Type *a, const clang::TemplateTypeParmDecl *b) { while (a->isPointerType() || a->isReferenceType()) diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index 0d03112eb54cf..afc0227e590d9 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -646,9 +646,12 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) { if (version > ImportNameVersion::swift2()) { // FIXME: Until Apple gets a chance to update UIKit's API notes, always use // the new name for certain properties. - if (auto *namedDecl = dyn_cast(decl)) + if (auto *namedDecl = dyn_cast(decl)) { if (importer::isSpecialUIKitStructZeroProperty(namedDecl)) version = ImportNameVersion::swift4_2(); + if (importer::isSpecialAppKitFunctionKeyProperty(namedDecl)) + return std::nullopt; + } // Dig out the attribute that specifies the Swift name. std::optional activeAttr; diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h index 086307ae9d11d..2861cb759bc2e 100644 --- a/lib/ClangImporter/ImporterImpl.h +++ b/lib/ClangImporter/ImporterImpl.h @@ -1976,6 +1976,12 @@ bool shouldSuppressDeclImport(const clang::Decl *decl); /// but are now renamed using the swift_name attribute. bool isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl); +/// Identifies certain AppKit constants that have overlay equivalents but are +/// also annotated with SwiftName API Notes attributes at the same time. Older +/// Clang versions were silently dropping the API Notes attribute on those +/// constants. +bool isSpecialAppKitFunctionKeyProperty(const clang::NamedDecl *decl); + /// \returns true if \p a has the same underlying type as \p b after removing /// any pointer/reference specifiers. Note that this does not currently look through /// nested types other than pointers or references. diff --git a/test/Interop/Cxx/objc-correctness/appkit-uikit.swift b/test/Interop/Cxx/objc-correctness/appkit-uikit.swift index 9ad15db16b5af..fc247f760e8ba 100644 --- a/test/Interop/Cxx/objc-correctness/appkit-uikit.swift +++ b/test/Interop/Cxx/objc-correctness/appkit-uikit.swift @@ -11,6 +11,9 @@ import AppKit var _: AttributeScopes.AppKitAttributes.UnderlineStyleAttribute! = nil var _ = NSEvent.SpecialKey.upArrow.rawValue +var _ = NSEvent.SpecialKey.enter.rawValue +var _ = NSUpArrowFunctionKey +var _ = NSEnterCharacter #elseif canImport(UIKit) import UIKit