@@ -1792,6 +1792,26 @@ applyPropertyOwnership(VarDecl *prop,
17921792}
17931793
17941794namespace {
1795+ // / Customized llvm::DenseMapInfo for storing borrowed APSInts.
1796+ struct APSIntRefDenseMapInfo {
1797+ static inline const llvm::APSInt *getEmptyKey () {
1798+ return llvm::DenseMapInfo<const llvm::APSInt *>::getEmptyKey ();
1799+ }
1800+ static inline const llvm::APSInt *getTombstoneKey () {
1801+ return llvm::DenseMapInfo<const llvm::APSInt *>::getTombstoneKey ();
1802+ }
1803+ static unsigned getHashValue (const llvm::APSInt *ptrVal) {
1804+ assert (ptrVal != getEmptyKey () && ptrVal != getTombstoneKey ());
1805+ return llvm::hash_value (*ptrVal);
1806+ }
1807+ static bool isEqual (const llvm::APSInt *lhs, const llvm::APSInt *rhs) {
1808+ if (lhs == rhs) return true ;
1809+ if (lhs == getEmptyKey () || rhs == getEmptyKey ()) return false ;
1810+ if (lhs == getTombstoneKey () || rhs == getTombstoneKey ()) return false ;
1811+ return *lhs == *rhs;
1812+ }
1813+ };
1814+
17951815 // / \brief Convert Clang declarations into the corresponding Swift
17961816 // / declarations.
17971817 class SwiftDeclConverter
@@ -2473,36 +2493,87 @@ namespace {
24732493 addEnumeratorsAsMembers = true ;
24742494 break ;
24752495 }
2476-
2477- for (auto ec = decl->enumerator_begin (), ecEnd = decl->enumerator_end ();
2478- ec != ecEnd; ++ec) {
2496+
2497+ llvm::SmallDenseMap<const llvm::APSInt *,
2498+ PointerUnion<const clang::EnumConstantDecl *,
2499+ EnumElementDecl *>, 8 ,
2500+ APSIntRefDenseMapInfo> canonicalEnumConstants;
2501+
2502+ if (enumKind == EnumKind::Enum) {
2503+ for (auto constant : decl->enumerators ()) {
2504+ if (Impl.isUnavailableInSwift (constant))
2505+ continue ;
2506+ canonicalEnumConstants.insert ({&constant->getInitVal (), constant});
2507+ }
2508+ }
2509+
2510+ for (auto constant : decl->enumerators ()) {
24792511 Decl *enumeratorDecl;
24802512 Decl *swift2EnumeratorDecl = nullptr ;
24812513 switch (enumKind) {
24822514 case EnumKind::Constants:
24832515 case EnumKind::Unknown:
2484- enumeratorDecl = Impl.importDecl (*ec , getActiveSwiftVersion ());
2516+ enumeratorDecl = Impl.importDecl (constant , getActiveSwiftVersion ());
24852517 swift2EnumeratorDecl =
2486- Impl.importDecl (*ec , ImportNameVersion::Swift2);
2518+ Impl.importDecl (constant , ImportNameVersion::Swift2);
24872519 break ;
24882520 case EnumKind::Options:
24892521 enumeratorDecl =
24902522 SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2491- .importOptionConstant (*ec , decl, enumeratorContext);
2523+ .importOptionConstant (constant , decl, enumeratorContext);
24922524 swift2EnumeratorDecl =
24932525 SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2494- .importOptionConstant (*ec , decl, enumeratorContext);
2526+ .importOptionConstant (constant , decl, enumeratorContext);
24952527 break ;
2496- case EnumKind::Enum:
2497- enumeratorDecl =
2498- SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2499- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext));
2528+ case EnumKind::Enum: {
2529+ auto canonicalCaseIter =
2530+ canonicalEnumConstants.find (&constant->getInitVal ());
2531+
2532+ if (canonicalCaseIter == canonicalEnumConstants.end ()) {
2533+ // Unavailable declarations get no special treatment.
2534+ enumeratorDecl =
2535+ SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2536+ .importEnumCase (constant, decl,
2537+ cast<EnumDecl>(enumeratorContext));
2538+ } else {
2539+ const clang::EnumConstantDecl *unimported =
2540+ canonicalCaseIter->
2541+ second.dyn_cast <const clang::EnumConstantDecl *>();
2542+
2543+ // Import the canonical enumerator for this case first.
2544+ if (unimported) {
2545+ enumeratorDecl = SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2546+ .importEnumCase (unimported, decl,
2547+ cast<EnumDecl>(enumeratorContext));
2548+ if (enumeratorDecl) {
2549+ canonicalCaseIter->getSecond () =
2550+ cast<EnumElementDecl>(enumeratorDecl);
2551+ }
2552+ } else {
2553+ enumeratorDecl =
2554+ canonicalCaseIter->second .get <EnumElementDecl *>();
2555+ }
2556+
2557+ if (unimported != constant && enumeratorDecl) {
2558+ ImportedName importedName =
2559+ Impl.importFullName (constant, getActiveSwiftVersion ());
2560+ Identifier name = importedName.getDeclName ().getBaseName ();
2561+ if (!name.empty ()) {
2562+ auto original = cast<ValueDecl>(enumeratorDecl);
2563+ enumeratorDecl = importEnumCaseAlias (name, constant, original,
2564+ decl, enumeratorContext);
2565+ }
2566+ }
2567+ }
2568+
25002569 swift2EnumeratorDecl =
25012570 SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2502- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext),
2571+ .importEnumCase (constant, decl,
2572+ cast<EnumDecl>(enumeratorContext),
25032573 enumeratorDecl);
25042574 break ;
25052575 }
2576+ }
25062577 if (!enumeratorDecl)
25072578 continue ;
25082579
@@ -2524,7 +2595,7 @@ namespace {
25242595 if (errorWrapper) {
25252596 auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
25262597 auto alias = importEnumCaseAlias (enumeratorValue->getName (),
2527- *ec ,
2598+ constant ,
25282599 enumeratorValue,
25292600 decl,
25302601 enumeratorContext,
@@ -4743,14 +4814,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
47434814 bool negative = false ;
47444815 llvm::APSInt rawValue = decl->getInitVal ();
47454816
4746- // Did we already import an enum constant for this enum with the
4747- // same value? If so, import it as a standalone constant.
4748- auto insertResult =
4749- Impl.EnumConstantValues .insert ({{clangEnum, rawValue}, nullptr });
4750- if (!insertResult.second )
4751- return importEnumCaseAlias (name, decl, insertResult.first ->second ,
4752- clangEnum, theEnum);
4753-
47544817 if (clangEnum->getIntegerType ()->isSignedIntegerOrEnumerationType () &&
47554818 rawValue.slt (0 )) {
47564819 rawValue = -rawValue;
@@ -4768,7 +4831,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
47684831 auto element = Impl.createDeclWithClangNode <EnumElementDecl>(
47694832 decl, Accessibility::Public, SourceLoc (), name, TypeLoc (), SourceLoc (),
47704833 rawValueExpr, theEnum);
4771- insertResult.first ->second = element;
47724834
47734835 // Give the enum element the appropriate type.
47744836 element->computeType ();
0 commit comments