Skip to content

Commit 37c4182

Browse files
committed
[cxx-interop] Allow old spelling of AppKit constants
AppKit defines certain constants in Objective-C, and then renames them into different constants in Swift, e.g. `NSUpArrowFunctionKey` is renamed into `NSEvent.SpecialKey.upArrow.rawValue`. In addition to that, AppKit also re-defines these constants in pure-Swift, which isn't the intended mechanism for renaming such constants. Prior to llvm/llvm-project#145947, Clang was silently dropping the `SwiftName` API Notes attributes on these constants due to a bug in the name validation mechanism. Clients of AppKit relied on that behavior and continued to use the old spelling in Swift. To preserve source compatibility and avoid a deprecation error, let's continue dropping the `SwiftName` attribute on select constants from AppKit. rdar://157485334
1 parent 8335ce5 commit 37c4182

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8680,6 +8680,26 @@ bool importer::isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl) {
86808680
return ident->isStr("UIEdgeInsetsZero") || ident->isStr("UIOffsetZero");
86818681
}
86828682

8683+
bool importer::isSpecialAppKitFunctionKeyProperty(
8684+
const clang::NamedDecl *decl) {
8685+
auto constant = dyn_cast<clang::EnumConstantDecl>(decl);
8686+
if (!constant)
8687+
return false;
8688+
8689+
auto module = constant->getOwningModule();
8690+
if (!module || module->getTopLevelModuleName() != "AppKit")
8691+
return false;
8692+
8693+
clang::DeclarationName name = constant->getDeclName();
8694+
const clang::IdentifierInfo *ident = name.getAsIdentifierInfo();
8695+
if (!ident)
8696+
return false;
8697+
auto rawName = ident->getName();
8698+
8699+
return rawName.starts_with("NS") &&
8700+
(rawName.ends_with("FunctionKey") || rawName.ends_with("Character"));
8701+
}
8702+
86838703
bool importer::hasSameUnderlyingType(const clang::Type *a,
86848704
const clang::TemplateTypeParmDecl *b) {
86858705
while (a->isPointerType() || a->isReferenceType())

lib/ClangImporter/ImportName.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,12 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
646646
if (version > ImportNameVersion::swift2()) {
647647
// FIXME: Until Apple gets a chance to update UIKit's API notes, always use
648648
// the new name for certain properties.
649-
if (auto *namedDecl = dyn_cast<clang::NamedDecl>(decl))
649+
if (auto *namedDecl = dyn_cast<clang::NamedDecl>(decl)) {
650650
if (importer::isSpecialUIKitStructZeroProperty(namedDecl))
651651
version = ImportNameVersion::swift4_2();
652+
if (importer::isSpecialAppKitFunctionKeyProperty(namedDecl))
653+
return std::nullopt;
654+
}
652655

653656
// Dig out the attribute that specifies the Swift name.
654657
std::optional<AnySwiftNameAttr> activeAttr;

lib/ClangImporter/ImporterImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,6 +1976,12 @@ bool shouldSuppressDeclImport(const clang::Decl *decl);
19761976
/// but are now renamed using the swift_name attribute.
19771977
bool isSpecialUIKitStructZeroProperty(const clang::NamedDecl *decl);
19781978

1979+
/// Identifies certain AppKit constants that have overlay equivalents but are
1980+
/// also annotated with SwiftName API Notes attributes at the same time. Older
1981+
/// Clang versions were silently dropping the API Notes attribute on those
1982+
/// constants.
1983+
bool isSpecialAppKitFunctionKeyProperty(const clang::NamedDecl *decl);
1984+
19791985
/// \returns true if \p a has the same underlying type as \p b after removing
19801986
/// any pointer/reference specifiers. Note that this does not currently look through
19811987
/// nested types other than pointers or references.

test/Interop/Cxx/objc-correctness/appkit-uikit.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import AppKit
1111
var _: AttributeScopes.AppKitAttributes.UnderlineStyleAttribute! = nil
1212

1313
var _ = NSEvent.SpecialKey.upArrow.rawValue
14+
var _ = NSEvent.SpecialKey.enter.rawValue
15+
var _ = NSUpArrowFunctionKey
16+
var _ = NSEnterCharacter
1417

1518
#elseif canImport(UIKit)
1619
import UIKit

0 commit comments

Comments
 (0)