@@ -1800,6 +1800,26 @@ applyPropertyOwnership(VarDecl *prop,
18001800}
18011801
18021802namespace {
1803+ // / Customized llvm::DenseMapInfo for storing borrowed APSInts.
1804+ struct APSIntRefDenseMapInfo {
1805+ static inline const llvm::APSInt *getEmptyKey () {
1806+ return llvm::DenseMapInfo<const llvm::APSInt *>::getEmptyKey ();
1807+ }
1808+ static inline const llvm::APSInt *getTombstoneKey () {
1809+ return llvm::DenseMapInfo<const llvm::APSInt *>::getTombstoneKey ();
1810+ }
1811+ static unsigned getHashValue (const llvm::APSInt *ptrVal) {
1812+ assert (ptrVal != getEmptyKey () && ptrVal != getTombstoneKey ());
1813+ return llvm::hash_value (*ptrVal);
1814+ }
1815+ static bool isEqual (const llvm::APSInt *lhs, const llvm::APSInt *rhs) {
1816+ if (lhs == rhs) return true ;
1817+ if (lhs == getEmptyKey () || rhs == getEmptyKey ()) return false ;
1818+ if (lhs == getTombstoneKey () || rhs == getTombstoneKey ()) return false ;
1819+ return *lhs == *rhs;
1820+ }
1821+ };
1822+
18031823 // / \brief Convert Clang declarations into the corresponding Swift
18041824 // / declarations.
18051825 class SwiftDeclConverter
@@ -2481,36 +2501,87 @@ namespace {
24812501 addEnumeratorsAsMembers = true ;
24822502 break ;
24832503 }
2484-
2485- for (auto ec = decl->enumerator_begin (), ecEnd = decl->enumerator_end ();
2486- ec != ecEnd; ++ec) {
2504+
2505+ llvm::SmallDenseMap<const llvm::APSInt *,
2506+ PointerUnion<const clang::EnumConstantDecl *,
2507+ EnumElementDecl *>, 8 ,
2508+ APSIntRefDenseMapInfo> canonicalEnumConstants;
2509+
2510+ if (enumKind == EnumKind::Enum) {
2511+ for (auto constant : decl->enumerators ()) {
2512+ if (Impl.isUnavailableInSwift (constant))
2513+ continue ;
2514+ canonicalEnumConstants.insert ({&constant->getInitVal (), constant});
2515+ }
2516+ }
2517+
2518+ for (auto constant : decl->enumerators ()) {
24872519 Decl *enumeratorDecl;
24882520 Decl *swift2EnumeratorDecl = nullptr ;
24892521 switch (enumKind) {
24902522 case EnumKind::Constants:
24912523 case EnumKind::Unknown:
2492- enumeratorDecl = Impl.importDecl (*ec , getActiveSwiftVersion ());
2524+ enumeratorDecl = Impl.importDecl (constant , getActiveSwiftVersion ());
24932525 swift2EnumeratorDecl =
2494- Impl.importDecl (*ec , ImportNameVersion::Swift2);
2526+ Impl.importDecl (constant , ImportNameVersion::Swift2);
24952527 break ;
24962528 case EnumKind::Options:
24972529 enumeratorDecl =
24982530 SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2499- .importOptionConstant (*ec , decl, enumeratorContext);
2531+ .importOptionConstant (constant , decl, enumeratorContext);
25002532 swift2EnumeratorDecl =
25012533 SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2502- .importOptionConstant (*ec , decl, enumeratorContext);
2534+ .importOptionConstant (constant , decl, enumeratorContext);
25032535 break ;
2504- case EnumKind::Enum:
2505- enumeratorDecl =
2506- SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2507- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext));
2536+ case EnumKind::Enum: {
2537+ auto canonicalCaseIter =
2538+ canonicalEnumConstants.find (&constant->getInitVal ());
2539+
2540+ if (canonicalCaseIter == canonicalEnumConstants.end ()) {
2541+ // Unavailable declarations get no special treatment.
2542+ enumeratorDecl =
2543+ SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2544+ .importEnumCase (constant, decl,
2545+ cast<EnumDecl>(enumeratorContext));
2546+ } else {
2547+ const clang::EnumConstantDecl *unimported =
2548+ canonicalCaseIter->
2549+ second.dyn_cast <const clang::EnumConstantDecl *>();
2550+
2551+ // Import the canonical enumerator for this case first.
2552+ if (unimported) {
2553+ enumeratorDecl = SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2554+ .importEnumCase (unimported, decl,
2555+ cast<EnumDecl>(enumeratorContext));
2556+ if (enumeratorDecl) {
2557+ canonicalCaseIter->getSecond () =
2558+ cast<EnumElementDecl>(enumeratorDecl);
2559+ }
2560+ } else {
2561+ enumeratorDecl =
2562+ canonicalCaseIter->second .get <EnumElementDecl *>();
2563+ }
2564+
2565+ if (unimported != constant && enumeratorDecl) {
2566+ ImportedName importedName =
2567+ Impl.importFullName (constant, getActiveSwiftVersion ());
2568+ Identifier name = importedName.getDeclName ().getBaseName ();
2569+ if (!name.empty ()) {
2570+ auto original = cast<ValueDecl>(enumeratorDecl);
2571+ enumeratorDecl = importEnumCaseAlias (name, constant, original,
2572+ decl, enumeratorContext);
2573+ }
2574+ }
2575+ }
2576+
25082577 swift2EnumeratorDecl =
25092578 SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2510- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext),
2579+ .importEnumCase (constant, decl,
2580+ cast<EnumDecl>(enumeratorContext),
25112581 enumeratorDecl);
25122582 break ;
25132583 }
2584+ }
25142585 if (!enumeratorDecl)
25152586 continue ;
25162587
@@ -2532,7 +2603,7 @@ namespace {
25322603 if (errorWrapper) {
25332604 auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
25342605 auto alias = importEnumCaseAlias (enumeratorValue->getName (),
2535- *ec ,
2606+ constant ,
25362607 enumeratorValue,
25372608 decl,
25382609 enumeratorContext,
@@ -4751,14 +4822,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
47514822 bool negative = false ;
47524823 llvm::APSInt rawValue = decl->getInitVal ();
47534824
4754- // Did we already import an enum constant for this enum with the
4755- // same value? If so, import it as a standalone constant.
4756- auto insertResult =
4757- Impl.EnumConstantValues .insert ({{clangEnum, rawValue}, nullptr });
4758- if (!insertResult.second )
4759- return importEnumCaseAlias (name, decl, insertResult.first ->second ,
4760- clangEnum, theEnum);
4761-
47624825 if (clangEnum->getIntegerType ()->isSignedIntegerOrEnumerationType () &&
47634826 rawValue.slt (0 )) {
47644827 rawValue = -rawValue;
@@ -4776,7 +4839,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
47764839 auto element = Impl.createDeclWithClangNode <EnumElementDecl>(
47774840 decl, Accessibility::Public, SourceLoc (), name, TypeLoc (), SourceLoc (),
47784841 rawValueExpr, theEnum);
4779- insertResult.first ->second = element;
47804842
47814843 // Give the enum element the appropriate type.
47824844 element->computeType ();
0 commit comments