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