mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ClangImporter] Classify enums using flag_enum and enum_extensibility (#8910)
These new Clang attributes identify whether an enum is intended to represent an option set or not, and whether the set of cases listed in the enum declaration is exhaustive. (Swift doesn't currently have a closed/open distinction for enums, so treat any C enum with enum_extensibility as a proper closed Swift enum, like we do with NS_ENUM.) Enums with neither attribute will continue to be imported as unique types. rdar://problem/28476618
This commit is contained in:
@@ -50,9 +50,20 @@ void EnumInfo::classifyEnum(ASTContext &ctx, const clang::EnumDecl *decl,
|
||||
nsErrorDomain = ctx.AllocateCopy(domainAttr->getErrorDomain()->getName());
|
||||
return;
|
||||
}
|
||||
if (decl->hasAttr<clang::FlagEnumAttr>()) {
|
||||
kind = EnumKind::Options;
|
||||
return;
|
||||
}
|
||||
if (decl->hasAttr<clang::EnumExtensibilityAttr>()) {
|
||||
// FIXME: Distinguish between open and closed enums.
|
||||
kind = EnumKind::Enum;
|
||||
return;
|
||||
}
|
||||
|
||||
// Was the enum declared using *_ENUM or *_OPTIONS?
|
||||
// FIXME: Use Clang attributes instead of groveling the macro expansion loc.
|
||||
// FIXME: Stop using these once flag_enum and enum_extensibility
|
||||
// have been adopted everywhere, or at least relegate them to Swift 3 mode
|
||||
// only.
|
||||
auto loc = decl->getLocStart();
|
||||
if (loc.isMacroID()) {
|
||||
StringRef MacroName = pp.getImmediateMacroName(loc);
|
||||
|
||||
@@ -2451,15 +2451,25 @@ public:
|
||||
"# define OBJC_DESIGNATED_INITIALIZER\n"
|
||||
"# endif\n"
|
||||
"#endif\n"
|
||||
"#if !defined(SWIFT_ENUM_ATTR)\n"
|
||||
"# if defined(__has_attribute) && "
|
||||
"__has_attribute(enum_extensibility)\n"
|
||||
"# define SWIFT_ENUM_ATTR "
|
||||
"__attribute__((enum_extensibility(open)))\n"
|
||||
"# else\n"
|
||||
"# define SWIFT_ENUM_ATTR\n"
|
||||
"# endif\n"
|
||||
"#endif\n"
|
||||
"#if !defined(SWIFT_ENUM)\n"
|
||||
"# define SWIFT_ENUM(_type, _name) "
|
||||
"enum _name : _type _name; "
|
||||
"enum SWIFT_ENUM_EXTRA _name : _type\n"
|
||||
"enum SWIFT_ENUM_ATTR SWIFT_ENUM_EXTRA _name : _type\n"
|
||||
"# if defined(__has_feature) && "
|
||||
"__has_feature(generalized_swift_name)\n"
|
||||
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) "
|
||||
"enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); "
|
||||
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_EXTRA _name : _type\n"
|
||||
"enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_ATTR "
|
||||
"SWIFT_ENUM_EXTRA _name : _type\n"
|
||||
"# else\n"
|
||||
"# define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) "
|
||||
"SWIFT_ENUM(_type, _name)\n"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define SWIFT_NAME(X) __attribute__((swift_name(#X)))
|
||||
|
||||
#define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
|
||||
#define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum __attribute__((enum_extensibility(open))) _name : _type
|
||||
|
||||
void drawString(const char *, int x, int y) SWIFT_NAME(drawString(_:x:y:));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import Foundation;
|
||||
|
||||
#define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
|
||||
#define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_ENUM_EXTRA _name : _type
|
||||
#define SWIFT_ENUM_NAMED(_type, _name, SWIFT_NAME) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_NAME); enum SWIFT_COMPILE_NAME(SWIFT_NAME) __attribute__((enum_extensibility(open))) SWIFT_ENUM_EXTRA _name : _type
|
||||
|
||||
typedef SWIFT_ENUM_NAMED(NSInteger, ObjCEnum, "SwiftEnum") {
|
||||
ObjCEnumOne = 1,
|
||||
|
||||
@@ -148,6 +148,8 @@ var qualifiedName = NSRuncingMode.mince
|
||||
var topLevelCaseName = RuncingMince // expected-error{{}}
|
||||
#endif
|
||||
|
||||
let _: EnumViaAttribute = .first
|
||||
|
||||
// NS_OPTIONS
|
||||
var withMince: NSRuncingOptions = .enableMince
|
||||
var withQuince: NSRuncingOptions = .enableQuince
|
||||
@@ -193,6 +195,7 @@ let audioComponentFlags2: FakeAudioComponentFlags = [.loadOutOfProcess]
|
||||
let objcFlags: objc_flags = [.taggedPointer, .swiftRefcount]
|
||||
|
||||
let optionsWithSwiftName: NSOptionsAlsoGetSwiftName = .Case
|
||||
let optionsViaAttribute: OptionsViaAttribute = [.first, .second]
|
||||
|
||||
// <rdar://problem/25168818> Don't import None members in NS_OPTIONS types
|
||||
#if !IRGEN
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
|
||||
|
||||
#define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type
|
||||
#define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum __attribute__((enum_extensibility(open))) SWIFT_ENUM_EXTRA _name : _type
|
||||
|
||||
typedef SWIFT_ENUM(NSInteger, Normal) {
|
||||
NormalOne = 0,
|
||||
@@ -10,20 +10,15 @@ typedef SWIFT_ENUM(NSInteger, Normal) {
|
||||
NormalThree
|
||||
};
|
||||
|
||||
// FIXME (#618): Use SWIFT_ENUM_NAMED() when support for that lands
|
||||
#undef SWIFT_ENUM
|
||||
#define SWIFT_ENUM(_type, _name) enum _name : _type _name SWIFT_COMPILE_NAME(SWIFT_ENUM_NAME); enum SWIFT_COMPILE_NAME(SWIFT_ENUM_NAME) SWIFT_ENUM_EXTRA _name : _type
|
||||
#define SWIFT_ENUM_NAMED(_type, _name, _swiftName) enum _name : _type _name SWIFT_COMPILE_NAME(_swiftName); enum SWIFT_COMPILE_NAME(_swiftName) __attribute__((enum_extensibility(open))) SWIFT_ENUM_EXTRA _name : _type
|
||||
|
||||
#define SWIFT_ENUM_NAME "SwiftEnum"
|
||||
typedef SWIFT_ENUM(NSInteger, ObjCEnum) {
|
||||
typedef SWIFT_ENUM_NAMED(NSInteger, ObjCEnum, "SwiftEnum") {
|
||||
ObjCEnumOne = 0,
|
||||
ObjCEnumTwo,
|
||||
ObjCEnumThree
|
||||
};
|
||||
|
||||
#undef SWIFT_ENUM_NAME
|
||||
#define SWIFT_ENUM_NAME "SwiftEnumTwo"
|
||||
typedef SWIFT_ENUM(NSInteger, ObjCEnumTwo) {
|
||||
typedef SWIFT_ENUM_NAMED(NSInteger, ObjCEnumTwo, "SwiftEnumTwo") {
|
||||
// the following shouldn't have their prefixes stripped
|
||||
SwiftEnumTwoA,
|
||||
SwiftEnumTwoB,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#ifndef SWIFT_ENUM
|
||||
# define SWIFT_ENUM(_type, _name) \
|
||||
enum _name : _type _name; \
|
||||
enum SWIFT_ENUM_EXTRA _name : _type
|
||||
enum __attribute__((enum_extensibility(open))) SWIFT_ENUM_EXTRA _name : _type
|
||||
#endif
|
||||
|
||||
// Renaming global variables.
|
||||
|
||||
@@ -29,6 +29,12 @@ typedef NS_ENUM(NSInteger, EnumWithAwkwardDeprecations) {
|
||||
EnumWithAwkward2BitProblems __attribute__((deprecated)) = EnumWithAwkwardNormalCase1,
|
||||
};
|
||||
|
||||
enum __attribute__((enum_extensibility(open))) EnumViaAttribute {
|
||||
EnumViaAttributeFirst = 1,
|
||||
EnumViaAttributeSecond = 2
|
||||
};
|
||||
|
||||
|
||||
// From <AudioUnit/AudioComponent.h>
|
||||
// The interesting feature of this enum is that the common prefix before
|
||||
// taking the enum name itself into account extends past the underscore.
|
||||
@@ -68,3 +74,8 @@ typedef CF_OPTIONS(UInt32, EmptySet2) {
|
||||
typedef CF_OPTIONS(UInt32, EmptySet3) {
|
||||
kEmptySet3None __attribute__((swift_name("None")))
|
||||
};
|
||||
|
||||
enum __attribute__((flag_enum)) OptionsViaAttribute {
|
||||
OptionsViaAttributeFirst = 1,
|
||||
OptionsViaAttributeSecond = 2
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user