@@ -1865,10 +1865,28 @@ namespace {
18651865 break ;
18661866 }
18671867
1868+ // / A table mapping each raw value used in this enum to the clang or
1869+ // / Swift decl for the "canonical" constant corresponding to that raw
1870+ // / value. The clang decls represent cases that haven't yet been imported;
1871+ // / the Swift decls represent cases that have been imported before.
1872+ // /
1873+ // / The problem we are trying to solve here is that C allows several
1874+ // / constants in the same enum to have the same raw value, but Swift does
1875+ // / not. We must therefore resolve collisions by selecting one case to be
1876+ // / the "canonical" one that will be imported as an \c EnumElementDecl
1877+ // / and importing the others as static \c VarDecl aliases of it. This
1878+ // / map knows which constants are canonical and can map a constant's raw
1879+ // / value to its corresponding canonical constant.
1880+ // /
1881+ // / Note that unavailable constants don't get inserted into this table,
1882+ // / so if an unavailable constant has no available alias, it simply won't
1883+ // / be present here. (Potential raw value conflicts doesn't really matter
1884+ // / for them because they will be imported as unavailable anyway.)
18681885 llvm::SmallDenseMap<llvm::APSInt,
18691886 PointerUnion<const clang::EnumConstantDecl *,
18701887 EnumElementDecl *>, 8 > canonicalEnumConstants;
18711888
1889+ // Fill in `canonicalEnumConstants` if it will be used.
18721890 if (enumKind == EnumKind::NonFrozenEnum ||
18731891 enumKind == EnumKind::FrozenEnum) {
18741892 for (auto constant : decl->enumerators ()) {
@@ -1943,24 +1961,32 @@ namespace {
19431961 SwiftDeclConverter (Impl, getActiveSwiftVersion ())
19441962 .importEnumCase (constant, decl, cast<EnumDecl>(result));
19451963 } else {
1946- const clang::EnumConstantDecl *unimported =
1964+ // Will initially be nullptr if `canonicalCaseIter` points to a
1965+ // memoized result.
1966+ const clang::EnumConstantDecl *canonConstant =
19471967 canonicalCaseIter->
19481968 second.dyn_cast <const clang::EnumConstantDecl *>();
19491969
1950- // Import the canonical enumerator for this case first.
1951- if (unimported) {
1970+ // First, either import the canonical constant for this case,
1971+ // or extract the memoized result of a previous import (and use it
1972+ // to populate `canonConstant`).
1973+ if (canonConstant) {
19521974 enumeratorDecl = SwiftDeclConverter (Impl, getActiveSwiftVersion ())
1953- .importEnumCase (unimported , decl, cast<EnumDecl>(result));
1975+ .importEnumCase (canonConstant , decl, cast<EnumDecl>(result));
19541976 if (enumeratorDecl) {
1977+ // Memoize so we end up in the `else` branch next time.
19551978 canonicalCaseIter->getSecond () =
19561979 cast<EnumElementDecl>(enumeratorDecl);
19571980 }
19581981 } else {
19591982 enumeratorDecl =
19601983 canonicalCaseIter->second .get <EnumElementDecl *>();
1984+ canonConstant =
1985+ cast<clang::EnumConstantDecl>(enumeratorDecl->getClangDecl ());
19611986 }
19621987
1963- if (unimported != constant && enumeratorDecl) {
1988+ // If `constant` wasn't the `canonConstant`, import it as an alias.
1989+ if (canonConstant != constant && enumeratorDecl) {
19641990 ImportedName importedName =
19651991 Impl.importFullName (constant, getActiveSwiftVersion ());
19661992 Identifier name = importedName.getBaseIdentifier (Impl.SwiftContext );
@@ -1976,6 +2002,7 @@ namespace {
19762002 }
19772003 }
19782004
2005+ // Now import each of the constant's alternate names.
19792006 Impl.forEachDistinctName (constant,
19802007 [&](ImportedName newName,
19812008 ImportNameVersion nameVersion) -> bool {
@@ -2026,6 +2053,19 @@ namespace {
20262053 }
20272054 }
20282055
2056+ // We don't always add an imported canonical constant to the enum's
2057+ // members right away, but we should have by the time we leave the loop.
2058+ // Verify that they are all in the enum's member list. (rdar://148213237)
2059+ if (CONDITIONAL_ASSERT_enabled ()) {
2060+ for (const auto &entry : canonicalEnumConstants) {
2061+ auto importedCase = entry.second .dyn_cast <EnumElementDecl *>();
2062+ if (!importedCase)
2063+ continue ;
2064+
2065+ ASSERT (llvm::is_contained (result->getCurrentMembers (), importedCase));
2066+ }
2067+ }
2068+
20292069 return result;
20302070 }
20312071
0 commit comments