Skip to content

Commit bca7330

Browse files
author
Nuri Amari
committed
Respect NS_REFINED_FOR_SWIFT importing anon enums
When an anonymous enum is imported, its imported name is under some circumstances derived from the type that it is backed by. NS_REFINED_FOR_SWIFT is a macro that produces a __attribute__((swift_private)) that when attached to a declaration, the imported name of this declaration should have two underscores prepended. When the name anonymous enum is derived from another declaration, and said declaration does not have the same swift private attribute, the __ is dropped. This patch fixes this.
1 parent f07c72b commit bca7330

File tree

4 files changed

+68
-2
lines changed

4 files changed

+68
-2
lines changed

lib/ClangImporter/ImportName.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1800,7 +1800,17 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
18001800
// If the typedef is available in Swift, the user will get ambiguity.
18011801
// It also means they may not have intended this API to be imported like this.
18021802
if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) {
1803-
result.setDeclName(swiftCtx.getIdentifier(typedefType->getDecl()->getName()));
1803+
StringRef baseName = typedefType->getDecl()->getName();
1804+
SmallString<16> swiftPrivateScratch;
1805+
// If this declaration has the swift_private attribute, prepend "__"
1806+
if (shouldBeSwiftPrivate(*this, D, version,
1807+
result.info.hasAsyncInfo)) {
1808+
swiftPrivateScratch = "__";
1809+
swiftPrivateScratch += baseName;
1810+
baseName = swiftPrivateScratch;
1811+
}
1812+
1813+
result.setDeclName(swiftCtx.getIdentifier(baseName));
18041814
result.setEffectiveContext(D->getDeclContext());
18051815
return result;
18061816
}

lib/ClangImporter/ImporterImpl.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1908,6 +1908,26 @@ inline Optional<const clang::EnumDecl *> findAnonymousEnumForTypedef(
19081908
if (found != foundDecls.end())
19091909
return cast<clang::EnumDecl>(found->get<clang::NamedDecl *>());
19101910

1911+
// If a swift_private attribute has been attached to the enum, its name will
1912+
// be prefixed with two underscores
1913+
llvm::SmallString<32> swiftPrivateName;
1914+
swiftPrivateName += "__";
1915+
swiftPrivateName += typedefDecl->getName();
1916+
foundDecls = lookupTable->lookup(
1917+
SerializedSwiftName(ctx.getIdentifier(swiftPrivateName)),
1918+
EffectiveClangContext());
1919+
1920+
auto swiftPrivateFound =
1921+
llvm::find_if(foundDecls, [](SwiftLookupTable::SingleEntry decl) {
1922+
return decl.is<clang::NamedDecl *>() &&
1923+
isa<clang::EnumDecl>(decl.get<clang::NamedDecl *>()) &&
1924+
decl.get<clang::NamedDecl *>()
1925+
->hasAttr<clang::SwiftPrivateAttr>();
1926+
});
1927+
1928+
if (swiftPrivateFound != foundDecls.end())
1929+
return cast<clang::EnumDecl>(swiftPrivateFound->get<clang::NamedDecl *>());
1930+
19111931
return None;
19121932
}
19131933

test/Interop/Cxx/enum/Inputs/c-enums-NS_OPTIONS.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ extern "C" {
1717

1818
#define CF_OPTIONS(_type, _name) _type __attribute__((availability(swift, unavailable))) _name; enum __CF_OPTIONS_ATTRIBUTES : _name
1919
#define NS_OPTIONS(_type, _name) CF_OPTIONS(_type, _name)
20+
#define NS_REFINED_FOR_SWIFT __attribute__((swift_private))
2021

2122
typedef unsigned long NSUInteger;
2223

@@ -26,4 +27,16 @@ typedef NS_OPTIONS(NSUInteger, NSBinarySearchingOptions) {
2627
NSBinarySearchingInsertionIndex = (1UL << 10),
2728
};
2829

29-
}
30+
typedef NS_OPTIONS(NSUInteger, NSAttributedStringFormattingOptions) {
31+
NSAttributedStringFormattingInsertArgumentAttributesWithoutMerging = 1 << 0,
32+
NSAttributedStringFormattingApplyReplacementIndexAttribute = 1 << 1,
33+
} NS_REFINED_FOR_SWIFT;
34+
35+
@interface NSAttributedString
36+
@end
37+
38+
@interface NSAttributedString (NSAttributedStringFormatting)
39+
- (instancetype)initWithOptions:(NSAttributedStringFormattingOptions)options
40+
NS_REFINED_FOR_SWIFT;
41+
@end
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=CenumsNSOptions -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
import CenumsNSOptions
5+
6+
// CHECK: typealias NSAttributedStringFormattingOptions = UInt
7+
// CHECK-NEXT: struct __NSAttributedStringFormattingOptions : OptionSet, @unchecked Sendable {
8+
// CHECK-NEXT: init(rawValue: UInt)
9+
// CHECK-NEXT: let rawValue: UInt
10+
// CHECK-NEXT: typealias RawValue = UInt
11+
// CHECK-NEXT: typealias Element = __NSAttributedStringFormattingOptions
12+
// CHECK-NEXT: typealias ArrayLiteralElement = __NSAttributedStringFormattingOptions
13+
// CHECK-NEXT: static var insertArgumentAttributesWithoutMerging: __NSAttributedStringFormattingOptions { get }
14+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "insertArgumentAttributesWithoutMerging")
15+
// CHECK-NEXT: static var InsertArgumentAttributesWithoutMerging: __NSAttributedStringFormattingOptions { get }
16+
// CHECK-NEXT: static var applyReplacementIndexAttribute: __NSAttributedStringFormattingOptions { get }
17+
// CHECK-NEXT: @available(swift, obsoleted: 3, renamed: "applyReplacementIndexAttribute")
18+
// CHECK-NEXT: static var ApplyReplacementIndexAttribute: __NSAttributedStringFormattingOptions { get }
19+
// CHECK-NEXT: }
20+
21+
// CHECK: extension NSAttributedString {
22+
// CHECK-NEXT: init!(__options options: __NSAttributedStringFormattingOptions = [])
23+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)