diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index b8540d3e12607..fe915dd30a9dc 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -2646,31 +2646,44 @@ ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument( } } else if (const clang::TypedefType *typedefType = type->getAs()) { - clang::TypedefNameDecl *typedefDecl = typedefType->getDecl(); - // Find the next decl in the same context. If this typedef is a part of an - // NS/CF_OPTIONS declaration, the next decl will be an enum. - auto declsInContext = typedefDecl->getDeclContext()->decls(); - auto declIter = llvm::find(declsInContext, typedefDecl); - if (declIter != declsInContext.end()) - declIter++; - if (declIter != declsInContext.end()) { - if (auto enumDecl = dyn_cast(*declIter)) { - if (auto cfOptionsTy = - nameImporter.getContext() - .getClangModuleLoader() - ->getTypeDefForCXXCFOptionsDefinition(enumDecl)) { - if (cfOptionsTy->getDecl() == typedefDecl) { - auto enumName = typedefDecl->getName(); - ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true, - enumName); - for (auto word : llvm::reverse(camel_case::getWords(enumName))) { - if (camel_case::sameWordIgnoreFirstCase(word, "options")) { - argumentAttrs.argumentKind = DefaultArgumentKind::EmptyArray; - } - } - return argumentAttrs; - } + // Get the AvailabilityAttr that would be set from CF/NS_OPTIONS + if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) { + // If we've taken this branch it means we have an enum type, and it is + // likely an integer or NSInteger that is being used by NS/CF_OPTIONS to + // behave like a C enum in the presence of C++. + auto enumName = typedefType->getDecl()->getName(); + ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true, enumName); + auto camelCaseWords = camel_case::getWords(enumName); + for (auto it = camelCaseWords.rbegin(); it != camelCaseWords.rend(); + ++it) { + auto word = *it; + auto next = std::next(it); + if (camel_case::sameWordIgnoreFirstCase(word, "options")) { + argumentAttrs.argumentKind = DefaultArgumentKind::EmptyArray; + return argumentAttrs; } + if (camel_case::sameWordIgnoreFirstCase(word, "units")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "domain")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "action")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "event")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "events") && + next != camelCaseWords.rend() && + camel_case::sameWordIgnoreFirstCase(*next, "control")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "state")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "unit")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "position") && + next != camelCaseWords.rend() && + camel_case::sameWordIgnoreFirstCase(*next, "scroll")) + return argumentAttrs; + if (camel_case::sameWordIgnoreFirstCase(word, "edge")) + return argumentAttrs; } } } diff --git a/test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h b/test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h index 81b407ed60e48..daeced9d2377f 100644 --- a/test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h +++ b/test/Interop/Cxx/enum/Inputs/c-enums-withOptions-omit.h @@ -1,57 +1,39 @@ -typedef unsigned NSUInteger; - -#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(NSUInteger, NSEnumerationOptions) { - NSEnumerationConcurrent = (1UL << 0), - NSEnumerationReverse = (1UL << 1), -}; +// Enum usage that is bitwise-able and assignable in C++, aka how CF_OPTIONS +// does things. +typedef int __attribute__((availability(swift, unavailable))) NSEnumerationOptions; +enum : NSEnumerationOptions { NSEnumerationConcurrent, NSEnumerationReverse }; @interface NSSet - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts ; @end -typedef CF_OPTIONS(NSUInteger, NSOrderedCollectionDifferenceCalculationOptions) { +typedef int __attribute__((availability(swift, unavailable))) NSOrderedCollectionDifferenceCalculationOptions; +enum : NSOrderedCollectionDifferenceCalculationOptions { NSOrderedCollectionDifferenceCalculationOptions1, NSOrderedCollectionDifferenceCalculationOptions2 }; -typedef CF_OPTIONS(NSUInteger, NSCalendarUnit) { - NSCalendarUnit1, - NSCalendarUnit2 -}; +typedef int __attribute__((availability(swift, unavailable))) NSCalendarUnit; +enum : NSCalendarUnit { NSCalendarUnit1, NSCalendarUnit2 }; -typedef CF_OPTIONS(NSUInteger, NSSearchPathDomainMask) { - NSSearchPathDomainMask1, - NSSearchPathDomainMask2 -}; +typedef int __attribute__((availability(swift, unavailable))) NSSearchPathDomainMask; +enum : NSSearchPathDomainMask { NSSearchPathDomainMask1, NSSearchPathDomainMask2 }; -typedef CF_OPTIONS(NSUInteger, NSControlCharacterAction) { - NSControlCharacterAction1, - NSControlCharacterAction2 -}; +typedef int __attribute__((availability(swift, unavailable))) NSControlCharacterAction; +enum : NSControlCharacterAction { NSControlCharacterAction1, NSControlCharacterAction2 }; -typedef CF_OPTIONS(NSUInteger, UIControlState) { - UIControlState1, - UIControlState2 -}; +typedef int __attribute__((availability(swift, unavailable))) UIControlState; +enum : UIControlState { UIControlState1, UIControlState2 }; -typedef CF_OPTIONS(NSUInteger, UITableViewCellStateMask) { - UITableViewCellStateMask1, - UITableViewCellStateMask2 -}; +typedef int __attribute__((availability(swift, unavailable))) UITableViewCellStateMask; +enum : UITableViewCellStateMask { UITableViewCellStateMask1, UITableViewCellStateMask2 }; -typedef CF_OPTIONS(NSUInteger, UIControlEvents) { - UIControlEvents1, - UIControlEvents2 -}; +typedef int __attribute__((availability(swift, unavailable))) UIControlEvents; +enum : UIControlEvents { UIControlEvents1, UIControlEvents2 }; -typedef CF_OPTIONS(NSUInteger, UITableViewScrollPosition) { +typedef int __attribute__((availability(swift, unavailable))) +UITableViewScrollPosition; +enum : UITableViewScrollPosition { UITableViewScrollPosition1, UITableViewScrollPosition2 }; diff --git a/test/Interop/Cxx/objc-correctness/Inputs/customNSOptions.h b/test/Interop/Cxx/objc-correctness/Inputs/customNSOptions.h deleted file mode 100644 index b666f4d713027..0000000000000 --- a/test/Interop/Cxx/objc-correctness/Inputs/customNSOptions.h +++ /dev/null @@ -1,6 +0,0 @@ -#include "CFOptions.h" - -typedef CF_OPTIONS(unsigned, MyControlFlags) { - MyControlFlagsNone = 0, - MyControlFlagsFirst -}; diff --git a/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap b/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap index 9d3a9bf5ac1f0..1d273bf94ff87 100644 --- a/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap +++ b/test/Interop/Cxx/objc-correctness/Inputs/module.modulemap @@ -9,10 +9,6 @@ module CxxClassWithNSStringInit { requires cplusplus } -module CustomNSOptions { - header "customNSOptions.h" -} - module NSOptionsMangling { header "NSOptionsMangling.h" } diff --git a/test/Interop/Cxx/objc-correctness/custom-nsoptions.swift b/test/Interop/Cxx/objc-correctness/custom-nsoptions.swift deleted file mode 100644 index 6c5e398643d10..0000000000000 --- a/test/Interop/Cxx/objc-correctness/custom-nsoptions.swift +++ /dev/null @@ -1,7 +0,0 @@ -// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -enable-objc-interop -enable-experimental-cxx-interop -// REQUIRES: objc_interop - -import CustomNSOptions - -let flags1: MyControlFlags = [] -let flags2: MyControlFlags = [.first]