Skip to content

Commit 06761a8

Browse files
committed
[cxx-interop] Use typedef's swift_name attr to rename anonymous enums.
1 parent c997944 commit 06761a8

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

lib/ClangImporter/ImportName.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,22 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
628628
activeAttr = decodeAttr(nameAttr);
629629
}
630630

631+
if (auto enumDecl = dyn_cast<clang::EnumDecl>(decl)) {
632+
// Intentionally don't get the cannonical type here.
633+
if (auto typedefType = dyn_cast<clang::TypedefType>(enumDecl->getIntegerType().getTypePtr())) {
634+
// If the typedef is available in Swift, the user will get ambiguity.
635+
// It also means they may not have intended this API to be imported like this.
636+
if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) {
637+
if (auto asyncAttr = typedefType->getDecl()->getAttr<clang::SwiftAsyncNameAttr>())
638+
activeAttr = decodeAttr(asyncAttr);
639+
if (!activeAttr) {
640+
if (auto nameAttr = typedefType->getDecl()->getAttr<clang::SwiftNameAttr>())
641+
activeAttr = decodeAttr(nameAttr);
642+
}
643+
}
644+
}
645+
}
646+
631647
Optional<AnySwiftNameAttr> result = activeAttr;
632648
llvm::VersionTuple bestSoFar;
633649
for (auto *attr : decl->attrs()) {

test/Interop/Cxx/enum/Inputs/anonymous-with-swift-name.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ typedef CF_OPTIONS(unsigned, CFColorMask) {
2222
inline SOColorMask useSOColorMask(SOColorMask mask) { return mask; }
2323
inline CFColorMask useCFColorMask(CFColorMask mask) { return mask; }
2424

25+
struct ParentStruct { };
26+
27+
typedef __attribute__((availability(swift, unavailable))) __attribute__((swift_name("ParentStruct.NewName"))) unsigned OldName;
28+
29+
enum __attribute__((flag_enum,enum_extensibility(open))) : OldName {
30+
kOldNameOne = (1 << 1),
31+
kOldNameTwo = (1 << 2)
32+
};
33+
34+
typedef __attribute__((availability(swift, unavailable))) __attribute__((swift_name("GlobalNewName"))) unsigned GlobalOldName;
35+
36+
enum __attribute__((flag_enum,enum_extensibility(open))) : GlobalOldName {
37+
kGlobalOldNameOne = (1 << 1),
38+
kGlobalOldNameTwo = (1 << 2)
39+
};
40+
2541
#if __OBJC__
2642
@interface ColorMaker
2743
- (void)makeColorWithOptions:(SOColorMask)opts;

test/Interop/Cxx/enum/anonymous-with-swift-name-module-interface.swift

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,50 @@
5656

5757
// CHECK: func useSOColorMask(_ mask: SOColorMask) -> SOColorMask
5858
// CHECK: func useCFColorMask(_ mask: CFColorMask) -> CFColorMask
59+
60+
// Test rename with "swift_name" attr:
61+
// CHECK: struct ParentStruct
62+
63+
// CHECK: @available(swift, obsoleted: 3, renamed: "ParentStruct.NewName")
64+
// CHECK: @available(*, unavailable, message: "Not available in Swift")
65+
// CHECK: typealias OldName = ParentStruct.NewName
66+
// CHECK: extension ParentStruct {
67+
// CHECK: @available(*, unavailable, message: "Not available in Swift")
68+
// CHECK: typealias NewName = UInt32
69+
// CHECK: struct NewName : OptionSet, @unchecked Sendable {
70+
// CHECK: init(rawValue: UInt32)
71+
// CHECK: let rawValue: UInt32
72+
// CHECK: typealias RawValue = UInt32
73+
// CHECK: typealias Element = ParentStruct.NewName
74+
// CHECK: typealias ArrayLiteralElement = ParentStruct.NewName
75+
// CHECK: static var one: ParentStruct.NewName { get }
76+
// CHECK: @available(swift, obsoleted: 3, renamed: "one")
77+
// CHECK: static var One: ParentStruct.NewName { get }
78+
// CHECK: static var two: ParentStruct.NewName { get }
79+
// CHECK: @available(swift, obsoleted: 3, renamed: "two")
80+
// CHECK: static var Two: ParentStruct.NewName { get }
81+
// CHECK: }
82+
// CHECK: }
83+
84+
// CHECK: @available(swift, obsoleted: 3, renamed: "ParentStruct.NewName")
85+
// CHECK: typealias OldName = ParentStruct.NewName
86+
// CHECK: @available(*, unavailable, message: "Not available in Swift")
87+
// CHECK: typealias GlobalNewName = UInt32
88+
// CHECK: @available(swift, obsoleted: 3, renamed: "GlobalNewName")
89+
// CHECK: @available(*, unavailable, message: "Not available in Swift")
90+
// CHECK: typealias GlobalOldName = GlobalNewName
91+
// CHECK: struct GlobalNewName : OptionSet, @unchecked Sendable {
92+
// CHECK: init(rawValue: UInt32)
93+
// CHECK: let rawValue: UInt32
94+
// CHECK: typealias RawValue = UInt32
95+
// CHECK: typealias Element = GlobalNewName
96+
// CHECK: typealias ArrayLiteralElement = GlobalNewName
97+
// CHECK: static var one: GlobalNewName { get }
98+
// CHECK: @available(swift, obsoleted: 3, renamed: "one")
99+
// CHECK: static var One: GlobalNewName { get }
100+
// CHECK: static var two: GlobalNewName { get }
101+
// CHECK: @available(swift, obsoleted: 3, renamed: "two")
102+
// CHECK: static var Two: GlobalNewName { get }
103+
// CHECK: }
104+
// CHECK: @available(swift, obsoleted: 3, renamed: "GlobalNewName")
105+
// CHECK: typealias GlobalOldName = GlobalNewName

0 commit comments

Comments
 (0)