diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 8dacf49cfd5a2..dcd7ee2088f17 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -6877,14 +6877,25 @@ const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition( if (!enumDecl->getDeclName().isEmpty()) return nullptr; - if (auto typedefType = dyn_cast( - enumDecl->getIntegerType().getTypePtr())) { - if (auto enumExtensibilityAttr = - typedefType->getDecl()->getAttr(); - enumExtensibilityAttr && + const clang::ElaboratedType *elaboratedType = + dyn_cast(enumDecl->getIntegerType().getTypePtr()); + if (auto typedefType = + elaboratedType + ? dyn_cast(elaboratedType->desugar()) + : dyn_cast( + enumDecl->getIntegerType().getTypePtr())) { + auto enumExtensibilityAttr = + elaboratedType + ? enumDecl->getAttr() + : typedefType->getDecl()->getAttr(); + const bool hasFlagEnumAttr = + elaboratedType ? enumDecl->hasAttr() + : typedefType->getDecl()->hasAttr(); + + if (enumExtensibilityAttr && enumExtensibilityAttr->getExtensibility() == clang::EnumExtensibilityAttr::Open && - typedefType->getDecl()->hasAttr()) { + hasFlagEnumAttr) { return Impl.isUnavailableInSwift(typedefType->getDecl()) ? typedefType : nullptr; } diff --git a/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.apinotes b/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.apinotes new file mode 100644 index 0000000000000..e8f3dbd34b73b --- /dev/null +++ b/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.apinotes @@ -0,0 +1,5 @@ +--- +Name: NSOptionsMangling +Tags: +- Name: UIControlState + SwiftName: UIControl.State diff --git a/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.h b/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.h new file mode 100644 index 0000000000000..6618d1c03c164 --- /dev/null +++ b/test/Interop/Cxx/objc-correctness/Inputs/NSOptionsMangling.h @@ -0,0 +1,22 @@ +#define __CF_OPTIONS_ATTRIBUTES __attribute__((flag_enum,enum_extensibility(open))) +#if (__cplusplus) +#define CF_OPTIONS(_type, _name) __attribute__((availability(swift,unavailable))) _type _name; enum __CF_OPTIONS_ATTRIBUTES : _name +#else +#define CF_OPTIONS(_type, _name) enum __CF_OPTIONS_ATTRIBUTES _name : _type _name; enum _name : _type +#endif + +typedef CF_OPTIONS(unsigned, UIControlState) { UIControlStateNormal = 0 }; + +#ifdef __cplusplus +#define UIKIT_EXTERN extern "C" __attribute__((visibility ("default"))) +#else +#define UIKIT_EXTERN extern __attribute__((visibility ("default"))) +#endif + +@interface UIView +@end + +UIKIT_EXTERN +@interface UIControl : UIView +@end + diff --git a/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap b/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap index a7b2476b3b07a..0d922784daf2a 100644 --- a/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap +++ b/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap @@ -9,3 +9,6 @@ module CxxClassWithNSStringInit [extern_c] { requires cplusplus } +module NSOptionsMangling { + header "NSOptionsMangling.h" +} diff --git a/test/Interop/Cxx/objc-correctness/ns-options-mangling.swift b/test/Interop/Cxx/objc-correctness/ns-options-mangling.swift new file mode 100644 index 0000000000000..4dc750a247a44 --- /dev/null +++ b/test/Interop/Cxx/objc-correctness/ns-options-mangling.swift @@ -0,0 +1,11 @@ +// RUN: %target-swift-frontend -I %S/Inputs -c -cxx-interoperability-mode=swift-5.9 %s -S -o - | %FileCheck %s +// RUN: %target-swift-frontend -I %S/Inputs -c %s -S -o - | %FileCheck %s + +// REQUIRES: objc_interop + +// CHECK: _$sSo14UIControlStateV4main7FooableACMc +// The following check is to ensure the conformance is mangled properly: +// protocol conformance descriptor for __C.UIControlState : main.Fooable in main +import NSOptionsMangling +protocol Fooable { } +extension UIControl.State: Fooable {}