Skip to content

Commit c9e619e

Browse files
authored
Merge pull request #61443 from NuriAmari/swift-ide-test
[CXX-Interop] Respect NS_REFINED_FOR_SWIFT importing anon enums
2 parents d977dd1 + bca7330 commit c9e619e

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)