Skip to content

Commit 0fd343f

Browse files
authored
Merge pull request #68855 from hyp/eng/revert-ns-options-x2-5.9
[5.9] revert "Revert "Revert "[cxx-interop] Import custom NS_OPTIONS correctly"""
2 parents 102c60b + ed1650e commit 0fd343f

File tree

9 files changed

+75
-104
lines changed

9 files changed

+75
-104
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,9 @@ class ClangModuleLoader : public ModuleLoader {
306306
virtual EffectiveClangContext getEffectiveClangContext(
307307
const NominalTypeDecl *nominal) = 0;
308308

309+
virtual const clang::TypedefType *
310+
getTypeDefForCXXCFOptionsDefinition(const clang::Decl *candidateDecl) = 0;
311+
309312
virtual SourceLoc importSourceLocation(clang::SourceLocation loc) = 0;
310313
};
311314

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,8 @@ class ClangImporter final : public ClangModuleLoader {
592592
/// Enable the symbolic import experimental feature for the given callback.
593593
void withSymbolicFeatureEnabled(llvm::function_ref<void(void)> callback);
594594

595-
static const clang::TypedefType *getTypedefForCXXCFOptionsDefinition(
596-
const clang::Decl *candidateDecl, const ASTContext &ctx);
595+
const clang::TypedefType *getTypeDefForCXXCFOptionsDefinition(
596+
const clang::Decl *candidateDecl) override;
597597

598598
SourceLoc importSourceLocation(clang::SourceLocation loc) override;
599599
};

lib/AST/ASTMangler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2551,8 +2551,8 @@ ASTMangler::getTypeDefForCXXCFOptionsDefinition(const ValueDecl *decl) {
25512551
if (!clangDecl)
25522552
return nullptr;
25532553

2554-
auto &ctx = decl->getASTContext();
2555-
return ClangImporter::getTypedefForCXXCFOptionsDefinition(clangDecl, ctx);
2554+
const auto &clangModuleLoader = decl->getASTContext().getClangModuleLoader();
2555+
return clangModuleLoader->getTypeDefForCXXCFOptionsDefinition(clangDecl);
25562556
}
25572557

25582558
const clang::NamedDecl *

lib/ClangImporter/ClangImporter.cpp

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6958,23 +6958,26 @@ void ClangImporter::withSymbolicFeatureEnabled(
69586958
oldImportSymbolicCXXDecls.get());
69596959
}
69606960

6961-
const clang::TypedefType *ClangImporter::getTypedefForCXXCFOptionsDefinition(
6962-
const clang::Decl *candidateDecl, const ASTContext &ctx) {
6963-
if (!ctx.LangOpts.EnableCXXInterop)
6961+
const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition(
6962+
const clang::Decl *candidateDecl) {
6963+
6964+
if (!Impl.SwiftContext.LangOpts.EnableCXXInterop)
69646965
return nullptr;
69656966

69666967
auto enumDecl = dyn_cast<clang::EnumDecl>(candidateDecl);
69676968
if (!enumDecl)
69686969
return nullptr;
6970+
69696971
if (!enumDecl->getDeclName().isEmpty())
69706972
return nullptr;
69716973

69726974
const clang::ElaboratedType *elaboratedType =
6973-
enumDecl->getIntegerType()->getAs<clang::ElaboratedType>();
6975+
dyn_cast<clang::ElaboratedType>(enumDecl->getIntegerType().getTypePtr());
69746976
if (auto typedefType =
69756977
elaboratedType
69766978
? dyn_cast<clang::TypedefType>(elaboratedType->desugar())
6977-
: enumDecl->getIntegerType()->getAs<clang::TypedefType>()) {
6979+
: dyn_cast<clang::TypedefType>(
6980+
enumDecl->getIntegerType().getTypePtr())) {
69786981
auto enumExtensibilityAttr =
69796982
elaboratedType
69806983
? enumDecl->getAttr<clang::EnumExtensibilityAttr>()
@@ -6987,13 +6990,8 @@ const clang::TypedefType *ClangImporter::getTypedefForCXXCFOptionsDefinition(
69876990
enumExtensibilityAttr->getExtensibility() ==
69886991
clang::EnumExtensibilityAttr::Open &&
69896992
hasFlagEnumAttr) {
6990-
// Make sure the typedef is marked as unavailable in Swift.
6991-
auto typedefDecl = typedefType->getDecl();
6992-
for (auto *attr :
6993-
typedefDecl->specific_attrs<clang::AvailabilityAttr>()) {
6994-
if (attr->getPlatform()->getName() == "swift")
6995-
return typedefType;
6996-
}
6993+
return Impl.isUnavailableInSwift(typedefType->getDecl()) ? typedefType
6994+
: nullptr;
69976995
}
69986996
}
69996997

lib/ClangImporter/ImportType.cpp

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,30 +2642,44 @@ ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument(
26422642
}
26432643
} else if (const clang::TypedefType *typedefType =
26442644
type->getAs<clang::TypedefType>()) {
2645-
clang::TypedefNameDecl *typedefDecl = typedefType->getDecl();
2646-
// Find the next decl in the same context. If this typedef is a part of an
2647-
// NS/CF_OPTIONS declaration, the next decl will be an enum.
2648-
auto declsInContext = typedefDecl->getDeclContext()->decls();
2649-
auto declIter = llvm::find(declsInContext, typedefDecl);
2650-
if (declIter != declsInContext.end())
2651-
declIter++;
2652-
if (declIter != declsInContext.end()) {
2653-
if (auto enumDecl = dyn_cast<clang::EnumDecl>(*declIter)) {
2654-
if (auto cfOptionsTy =
2655-
ClangImporter::getTypedefForCXXCFOptionsDefinition(
2656-
enumDecl, nameImporter.getContext())) {
2657-
if (cfOptionsTy->getDecl() == typedefDecl) {
2658-
auto enumName = typedefDecl->getName();
2659-
ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true,
2660-
enumName);
2661-
for (auto word : llvm::reverse(camel_case::getWords(enumName))) {
2662-
if (camel_case::sameWordIgnoreFirstCase(word, "options")) {
2663-
argumentAttrs.argumentKind = DefaultArgumentKind::EmptyArray;
2664-
}
2665-
}
2666-
return argumentAttrs;
2667-
}
2645+
// Get the AvailabilityAttr that would be set from CF/NS_OPTIONS
2646+
if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) {
2647+
// If we've taken this branch it means we have an enum type, and it is
2648+
// likely an integer or NSInteger that is being used by NS/CF_OPTIONS to
2649+
// behave like a C enum in the presence of C++.
2650+
auto enumName = typedefType->getDecl()->getName();
2651+
ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true, enumName);
2652+
auto camelCaseWords = camel_case::getWords(enumName);
2653+
for (auto it = camelCaseWords.rbegin(); it != camelCaseWords.rend();
2654+
++it) {
2655+
auto word = *it;
2656+
auto next = std::next(it);
2657+
if (camel_case::sameWordIgnoreFirstCase(word, "options")) {
2658+
argumentAttrs.argumentKind = DefaultArgumentKind::EmptyArray;
2659+
return argumentAttrs;
26682660
}
2661+
if (camel_case::sameWordIgnoreFirstCase(word, "units"))
2662+
return argumentAttrs;
2663+
if (camel_case::sameWordIgnoreFirstCase(word, "domain"))
2664+
return argumentAttrs;
2665+
if (camel_case::sameWordIgnoreFirstCase(word, "action"))
2666+
return argumentAttrs;
2667+
if (camel_case::sameWordIgnoreFirstCase(word, "event"))
2668+
return argumentAttrs;
2669+
if (camel_case::sameWordIgnoreFirstCase(word, "events") &&
2670+
next != camelCaseWords.rend() &&
2671+
camel_case::sameWordIgnoreFirstCase(*next, "control"))
2672+
return argumentAttrs;
2673+
if (camel_case::sameWordIgnoreFirstCase(word, "state"))
2674+
return argumentAttrs;
2675+
if (camel_case::sameWordIgnoreFirstCase(word, "unit"))
2676+
return argumentAttrs;
2677+
if (camel_case::sameWordIgnoreFirstCase(word, "position") &&
2678+
next != camelCaseWords.rend() &&
2679+
camel_case::sameWordIgnoreFirstCase(*next, "scroll"))
2680+
return argumentAttrs;
2681+
if (camel_case::sameWordIgnoreFirstCase(word, "edge"))
2682+
return argumentAttrs;
26692683
}
26702684
}
26712685
}

test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,39 @@
1-
typedef unsigned NSUInteger;
2-
3-
#define __CF_OPTIONS_ATTRIBUTES __attribute__((flag_enum,enum_extensibility(open)))
4-
#if (__cplusplus)
5-
#define CF_OPTIONS(_type, _name) __attribute__((availability(swift,unavailable))) _type _name; enum __CF_OPTIONS_ATTRIBUTES : _name
6-
#else
7-
#define CF_OPTIONS(_type, _name) enum __CF_OPTIONS_ATTRIBUTES _name : _type _name; enum _name : _type
8-
#endif
9-
10-
typedef CF_OPTIONS(NSUInteger, NSEnumerationOptions) {
11-
NSEnumerationConcurrent = (1UL << 0),
12-
NSEnumerationReverse = (1UL << 1),
13-
};
1+
// Enum usage that is bitwise-able and assignable in C++, aka how CF_OPTIONS
2+
// does things.
3+
typedef int __attribute__((availability(swift, unavailable))) NSEnumerationOptions;
4+
enum : NSEnumerationOptions { NSEnumerationConcurrent, NSEnumerationReverse };
145

156
@interface NSSet
167
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts ;
178
@end
189

19-
typedef CF_OPTIONS(NSUInteger, NSOrderedCollectionDifferenceCalculationOptions) {
10+
typedef int __attribute__((availability(swift, unavailable))) NSOrderedCollectionDifferenceCalculationOptions;
11+
enum : NSOrderedCollectionDifferenceCalculationOptions {
2012
NSOrderedCollectionDifferenceCalculationOptions1,
2113
NSOrderedCollectionDifferenceCalculationOptions2
2214
};
2315

24-
typedef CF_OPTIONS(NSUInteger, NSCalendarUnit) {
25-
NSCalendarUnit1,
26-
NSCalendarUnit2
27-
};
16+
typedef int __attribute__((availability(swift, unavailable))) NSCalendarUnit;
17+
enum : NSCalendarUnit { NSCalendarUnit1, NSCalendarUnit2 };
2818

29-
typedef CF_OPTIONS(NSUInteger, NSSearchPathDomainMask) {
30-
NSSearchPathDomainMask1,
31-
NSSearchPathDomainMask2
32-
};
19+
typedef int __attribute__((availability(swift, unavailable))) NSSearchPathDomainMask;
20+
enum : NSSearchPathDomainMask { NSSearchPathDomainMask1, NSSearchPathDomainMask2 };
3321

34-
typedef CF_OPTIONS(NSUInteger, NSControlCharacterAction) {
35-
NSControlCharacterAction1,
36-
NSControlCharacterAction2
37-
};
22+
typedef int __attribute__((availability(swift, unavailable))) NSControlCharacterAction;
23+
enum : NSControlCharacterAction { NSControlCharacterAction1, NSControlCharacterAction2 };
3824

39-
typedef CF_OPTIONS(NSUInteger, UIControlState) {
40-
UIControlState1,
41-
UIControlState2
42-
};
25+
typedef int __attribute__((availability(swift, unavailable))) UIControlState;
26+
enum : UIControlState { UIControlState1, UIControlState2 };
4327

44-
typedef CF_OPTIONS(NSUInteger, UITableViewCellStateMask) {
45-
UITableViewCellStateMask1,
46-
UITableViewCellStateMask2
47-
};
28+
typedef int __attribute__((availability(swift, unavailable))) UITableViewCellStateMask;
29+
enum : UITableViewCellStateMask { UITableViewCellStateMask1, UITableViewCellStateMask2 };
4830

49-
typedef CF_OPTIONS(NSUInteger, UIControlEvents) {
50-
UIControlEvents1,
51-
UIControlEvents2
52-
};
31+
typedef int __attribute__((availability(swift, unavailable))) UIControlEvents;
32+
enum : UIControlEvents { UIControlEvents1, UIControlEvents2 };
5333

54-
typedef CF_OPTIONS(NSUInteger, UITableViewScrollPosition) {
34+
typedef int __attribute__((availability(swift, unavailable)))
35+
UITableViewScrollPosition;
36+
enum : UITableViewScrollPosition {
5537
UITableViewScrollPosition1,
5638
UITableViewScrollPosition2
5739
};

test/Interop/Cxx/objc-correctness/Inputs/customNSOptions.h

Lines changed: 0 additions & 6 deletions
This file was deleted.

test/Interop/Cxx/objc-correctness/Inputs/module.modulemap

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ module CxxClassWithNSStringInit {
99
requires cplusplus
1010
}
1111

12-
module CustomNSOptions {
13-
header "customNSOptions.h"
14-
}
15-
1612
module NSOptionsMangling {
1713
header "NSOptionsMangling.h"
1814
}

test/Interop/Cxx/objc-correctness/custom-nsoptions.swift

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)