@@ -1792,6 +1792,26 @@ applyPropertyOwnership(VarDecl *prop,
1792
1792
}
1793
1793
1794
1794
namespace {
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
+
1795
1815
// / \brief Convert Clang declarations into the corresponding Swift
1796
1816
// / declarations.
1797
1817
class SwiftDeclConverter
@@ -2473,36 +2493,87 @@ namespace {
2473
2493
addEnumeratorsAsMembers = true ;
2474
2494
break ;
2475
2495
}
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 ()) {
2479
2511
Decl *enumeratorDecl;
2480
2512
Decl *swift2EnumeratorDecl = nullptr ;
2481
2513
switch (enumKind) {
2482
2514
case EnumKind::Constants:
2483
2515
case EnumKind::Unknown:
2484
- enumeratorDecl = Impl.importDecl (*ec , getActiveSwiftVersion ());
2516
+ enumeratorDecl = Impl.importDecl (constant , getActiveSwiftVersion ());
2485
2517
swift2EnumeratorDecl =
2486
- Impl.importDecl (*ec , ImportNameVersion::Swift2);
2518
+ Impl.importDecl (constant , ImportNameVersion::Swift2);
2487
2519
break ;
2488
2520
case EnumKind::Options:
2489
2521
enumeratorDecl =
2490
2522
SwiftDeclConverter (Impl, getActiveSwiftVersion ())
2491
- .importOptionConstant (*ec , decl, enumeratorContext);
2523
+ .importOptionConstant (constant , decl, enumeratorContext);
2492
2524
swift2EnumeratorDecl =
2493
2525
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2494
- .importOptionConstant (*ec , decl, enumeratorContext);
2526
+ .importOptionConstant (constant , decl, enumeratorContext);
2495
2527
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
+
2500
2569
swift2EnumeratorDecl =
2501
2570
SwiftDeclConverter (Impl, ImportNameVersion::Swift2)
2502
- .importEnumCase (*ec, decl, cast<EnumDecl>(enumeratorContext),
2571
+ .importEnumCase (constant, decl,
2572
+ cast<EnumDecl>(enumeratorContext),
2503
2573
enumeratorDecl);
2504
2574
break ;
2505
2575
}
2576
+ }
2506
2577
if (!enumeratorDecl)
2507
2578
continue ;
2508
2579
@@ -2524,7 +2595,7 @@ namespace {
2524
2595
if (errorWrapper) {
2525
2596
auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
2526
2597
auto alias = importEnumCaseAlias (enumeratorValue->getName (),
2527
- *ec ,
2598
+ constant ,
2528
2599
enumeratorValue,
2529
2600
decl,
2530
2601
enumeratorContext,
@@ -4743,14 +4814,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4743
4814
bool negative = false ;
4744
4815
llvm::APSInt rawValue = decl->getInitVal ();
4745
4816
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
-
4754
4817
if (clangEnum->getIntegerType ()->isSignedIntegerOrEnumerationType () &&
4755
4818
rawValue.slt (0 )) {
4756
4819
rawValue = -rawValue;
@@ -4768,7 +4831,6 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
4768
4831
auto element = Impl.createDeclWithClangNode <EnumElementDecl>(
4769
4832
decl, Accessibility::Public, SourceLoc (), name, TypeLoc (), SourceLoc (),
4770
4833
rawValueExpr, theEnum);
4771
- insertResult.first ->second = element;
4772
4834
4773
4835
// Give the enum element the appropriate type.
4774
4836
element->computeType ();
0 commit comments