@@ -1788,6 +1788,26 @@ applyPropertyOwnership(VarDecl *prop,
1788
1788
}
1789
1789
1790
1790
namespace {
1791
+ // / Customized llvm::DenseMapInfo for storing borrowed APSInts.
1792
+ struct APSIntRefDenseMapInfo {
1793
+ static inline const llvm::APSInt *getEmptyKey () {
1794
+ return llvm::DenseMapInfo<const llvm::APSInt *>::getEmptyKey ();
1795
+ }
1796
+ static inline const llvm::APSInt *getTombstoneKey () {
1797
+ return llvm::DenseMapInfo<const llvm::APSInt *>::getTombstoneKey ();
1798
+ }
1799
+ static unsigned getHashValue (const llvm::APSInt *ptrVal) {
1800
+ assert (ptrVal != getEmptyKey () && ptrVal != getTombstoneKey ());
1801
+ return llvm::hash_value (*ptrVal);
1802
+ }
1803
+ static bool isEqual (const llvm::APSInt *lhs, const llvm::APSInt *rhs) {
1804
+ if (lhs == rhs) return true ;
1805
+ if (lhs == getEmptyKey () || rhs == getEmptyKey ()) return false ;
1806
+ if (lhs == getTombstoneKey () || rhs == getTombstoneKey ()) return false ;
1807
+ return *lhs == *rhs;
1808
+ }
1809
+ };
1810
+
1791
1811
// / \brief Convert Clang declarations into the corresponding Swift
1792
1812
// / declarations.
1793
1813
class SwiftDeclConverter
@@ -2469,36 +2489,87 @@ namespace {
2469
2489
addEnumeratorsAsMembers = true ;
2470
2490
break ;
2471
2491
}
2472
-
2473
- for (auto ec = decl->enumerator_begin (), ecEnd = decl->enumerator_end ();
2474
- ec != ecEnd; ++ec) {
2492
+
2493
+ llvm::SmallDenseMap<const llvm::APSInt *,
2494
+ PointerUnion<const clang::EnumConstantDecl *,
2495
+ EnumElementDecl *>, 8 ,
2496
+ APSIntRefDenseMapInfo> canonicalEnumConstants;
2497
+
2498
+ if (enumKind == EnumKind::Enum) {
2499
+ for (auto constant : decl->enumerators ()) {
2500
+ if (Impl.isUnavailableInSwift (constant))
2501
+ continue ;
2502
+ canonicalEnumConstants.insert ({&constant->getInitVal (), constant});
2503
+ }
2504
+ }
2505
+
2506
+ for (auto constant : decl->enumerators ()) {
2475
2507
Decl *enumeratorDecl;
2476
2508
Decl *swift2EnumeratorDecl = nullptr ;
2477
2509
switch (enumKind) {
2478
2510
case EnumKind::Constants:
2479
2511
case EnumKind::Unknown:
2480
- enumeratorDecl = Impl.importDecl (*ec , getActiveSwiftVersion ());
2512
+ enumeratorDecl = Impl.importDecl (constant , getActiveSwiftVersion ());
2481
2513
swift2EnumeratorDecl =
2482
- Impl.importDecl (*ec , ImportNameVersion::Swift2);
2514
+ Impl.importDecl (constant , ImportNameVersion::Swift2);
2483
2515
break ;
2484
2516
case EnumKind::Options:
2485
2517
enumeratorDecl =
2486
2518
SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2487
- .importOptionConstant (*ec , decl, enumeratorContext);
2519
+ .importOptionConstant (constant , decl, enumeratorContext);
2488
2520
swift2EnumeratorDecl =
2489
2521
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2490
- .importOptionConstant (*ec , decl, enumeratorContext);
2522
+ .importOptionConstant (constant , decl, enumeratorContext);
2491
2523
break ;
2492
- case EnumKind::Enum:
2493
- enumeratorDecl =
2494
- SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2495
- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext));
2524
+ case EnumKind::Enum: {
2525
+ auto canonicalCaseIter =
2526
+ canonicalEnumConstants.find (&constant->getInitVal ());
2527
+
2528
+ if (canonicalCaseIter == canonicalEnumConstants.end ()) {
2529
+ // Unavailable declarations get no special treatment.
2530
+ enumeratorDecl =
2531
+ SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2532
+ .importEnumCase (constant, decl,
2533
+ cast<EnumDecl>(enumeratorContext));
2534
+ } else {
2535
+ const clang::EnumConstantDecl *unimported =
2536
+ canonicalCaseIter->
2537
+ second.dyn_cast <const clang::EnumConstantDecl *>();
2538
+
2539
+ // Import the canonical enumerator for this case first.
2540
+ if (unimported) {
2541
+ enumeratorDecl = SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2542
+ .importEnumCase (unimported, decl,
2543
+ cast<EnumDecl>(enumeratorContext));
2544
+ if (enumeratorDecl) {
2545
+ canonicalCaseIter->getSecond () =
2546
+ cast<EnumElementDecl>(enumeratorDecl);
2547
+ }
2548
+ } else {
2549
+ enumeratorDecl =
2550
+ canonicalCaseIter->second .get <EnumElementDecl *>();
2551
+ }
2552
+
2553
+ if (unimported != constant && enumeratorDecl) {
2554
+ ImportedName importedName =
2555
+ Impl.importFullName (constant, getActiveSwiftVersion ());
2556
+ Identifier name = importedName.getDeclName ().getBaseName ();
2557
+ if (!name.empty ()) {
2558
+ auto original = cast<ValueDecl>(enumeratorDecl);
2559
+ enumeratorDecl = importEnumCaseAlias (name, constant, original,
2560
+ decl, enumeratorContext);
2561
+ }
2562
+ }
2563
+ }
2564
+
2496
2565
swift2EnumeratorDecl =
2497
2566
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2498
- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext),
2567
+ .importEnumCase (constant, decl,
2568
+ cast<EnumDecl>(enumeratorContext),
2499
2569
enumeratorDecl);
2500
2570
break ;
2501
2571
}
2572
+ }
2502
2573
if (!enumeratorDecl)
2503
2574
continue ;
2504
2575
@@ -2520,7 +2591,7 @@ namespace {
2520
2591
if (errorWrapper) {
2521
2592
auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
2522
2593
auto alias = importEnumCaseAlias (enumeratorValue->getName (),
2523
- *ec ,
2594
+ constant ,
2524
2595
enumeratorValue,
2525
2596
decl,
2526
2597
enumeratorContext,
@@ -4739,14 +4810,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4739
4810
bool negative = false ;
4740
4811
llvm::APSInt rawValue = decl->getInitVal ();
4741
4812
4742
- // Did we already import an enum constant for this enum with the
4743
- // same value? If so, import it as a standalone constant.
4744
- auto insertResult =
4745
- Impl.EnumConstantValues .insert ({{clangEnum, rawValue}, nullptr });
4746
- if (!insertResult.second )
4747
- return importEnumCaseAlias (name, decl, insertResult.first ->second ,
4748
- clangEnum, theEnum);
4749
-
4750
4813
if (clangEnum->getIntegerType ()->isSignedIntegerOrEnumerationType () &&
4751
4814
rawValue.slt (0 )) {
4752
4815
rawValue = -rawValue;
@@ -4764,7 +4827,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4764
4827
auto element = Impl.createDeclWithClangNode <EnumElementDecl>(
4765
4828
decl, Accessibility::Public, SourceLoc (), name, TypeLoc (), SourceLoc (),
4766
4829
rawValueExpr, theEnum);
4767
- insertResult.first ->second = element;
4768
4830
4769
4831
// Give the enum element the appropriate type.
4770
4832
element->computeType ();
0 commit comments