@@ -1800,6 +1800,26 @@ applyPropertyOwnership(VarDecl *prop,
1800
1800
}
1801
1801
1802
1802
namespace {
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
+
1803
1823
// / \brief Convert Clang declarations into the corresponding Swift
1804
1824
// / declarations.
1805
1825
class SwiftDeclConverter
@@ -2481,36 +2501,87 @@ namespace {
2481
2501
addEnumeratorsAsMembers = true ;
2482
2502
break ;
2483
2503
}
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 ()) {
2487
2519
Decl *enumeratorDecl;
2488
2520
Decl *swift2EnumeratorDecl = nullptr ;
2489
2521
switch (enumKind) {
2490
2522
case EnumKind::Constants:
2491
2523
case EnumKind::Unknown:
2492
- enumeratorDecl = Impl.importDecl (*ec , getActiveSwiftVersion ());
2524
+ enumeratorDecl = Impl.importDecl (constant , getActiveSwiftVersion ());
2493
2525
swift2EnumeratorDecl =
2494
- Impl.importDecl (*ec , ImportNameVersion::Swift2);
2526
+ Impl.importDecl (constant , ImportNameVersion::Swift2);
2495
2527
break ;
2496
2528
case EnumKind::Options:
2497
2529
enumeratorDecl =
2498
2530
SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2499
- .importOptionConstant (*ec , decl, enumeratorContext);
2531
+ .importOptionConstant (constant , decl, enumeratorContext);
2500
2532
swift2EnumeratorDecl =
2501
2533
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2502
- .importOptionConstant (*ec , decl, enumeratorContext);
2534
+ .importOptionConstant (constant , decl, enumeratorContext);
2503
2535
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
+
2508
2577
swift2EnumeratorDecl =
2509
2578
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2510
- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext),
2579
+ .importEnumCase (constant, decl,
2580
+ cast<EnumDecl>(enumeratorContext),
2511
2581
enumeratorDecl);
2512
2582
break ;
2513
2583
}
2584
+ }
2514
2585
if (!enumeratorDecl)
2515
2586
continue ;
2516
2587
@@ -2532,7 +2603,7 @@ namespace {
2532
2603
if (errorWrapper) {
2533
2604
auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
2534
2605
auto alias = importEnumCaseAlias (enumeratorValue->getName (),
2535
- *ec ,
2606
+ constant ,
2536
2607
enumeratorValue,
2537
2608
decl,
2538
2609
enumeratorContext,
@@ -4751,14 +4822,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4751
4822
bool negative = false ;
4752
4823
llvm::APSInt rawValue = decl->getInitVal ();
4753
4824
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
-
4762
4825
if (clangEnum->getIntegerType ()->isSignedIntegerOrEnumerationType () &&
4763
4826
rawValue.slt (0 )) {
4764
4827
rawValue = -rawValue;
@@ -4776,7 +4839,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4776
4839
auto element = Impl.createDeclWithClangNode <EnumElementDecl>(
4777
4840
decl, Accessibility::Public, SourceLoc (), name, TypeLoc (), SourceLoc (),
4778
4841
rawValueExpr, theEnum);
4779
- insertResult.first ->second = element;
4780
4842
4781
4843
// Give the enum element the appropriate type.
4782
4844
element->computeType ();
0 commit comments