@@ -1866,10 +1866,28 @@ namespace {
1866
1866
break;
1867
1867
}
1868
1868
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.)
1869
1886
llvm::SmallDenseMap<llvm::APSInt,
1870
1887
PointerUnion<const clang::EnumConstantDecl *,
1871
1888
EnumElementDecl *>, 8> canonicalEnumConstants;
1872
1889
1890
+ // Fill in `canonicalEnumConstants` if it will be used.
1873
1891
if (enumKind == EnumKind::NonFrozenEnum ||
1874
1892
enumKind == EnumKind::FrozenEnum) {
1875
1893
for (auto constant : decl->enumerators()) {
@@ -1944,24 +1962,32 @@ namespace {
1944
1962
SwiftDeclConverter(Impl, getActiveSwiftVersion())
1945
1963
.importEnumCase(constant, decl, cast<EnumDecl>(result));
1946
1964
} else {
1947
- const clang::EnumConstantDecl *unimported =
1965
+ // Will initially be nullptr if `canonicalCaseIter` points to a
1966
+ // memoized result.
1967
+ const clang::EnumConstantDecl *canonConstant =
1948
1968
canonicalCaseIter->
1949
1969
second.dyn_cast<const clang::EnumConstantDecl *>();
1950
1970
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) {
1953
1975
enumeratorDecl = SwiftDeclConverter(Impl, getActiveSwiftVersion())
1954
- .importEnumCase(unimported , decl, cast<EnumDecl>(result));
1976
+ .importEnumCase(canonConstant , decl, cast<EnumDecl>(result));
1955
1977
if (enumeratorDecl) {
1978
+ // Memoize so we end up in the `else` branch next time.
1956
1979
canonicalCaseIter->getSecond() =
1957
1980
cast<EnumElementDecl>(enumeratorDecl);
1958
1981
}
1959
1982
} else {
1960
1983
enumeratorDecl =
1961
1984
canonicalCaseIter->second.get<EnumElementDecl *>();
1985
+ canonConstant =
1986
+ cast<clang::EnumConstantDecl>(enumeratorDecl->getClangDecl());
1962
1987
}
1963
1988
1964
- if (unimported != constant && enumeratorDecl) {
1989
+ // If `constant` wasn't the `canonConstant`, import it as an alias.
1990
+ if (canonConstant != constant && enumeratorDecl) {
1965
1991
ImportedName importedName =
1966
1992
Impl.importFullName(constant, getActiveSwiftVersion());
1967
1993
Identifier name = importedName.getBaseIdentifier(Impl.SwiftContext);
@@ -1977,6 +2003,7 @@ namespace {
1977
2003
}
1978
2004
}
1979
2005
2006
+ // Now import each of the constant's alternate names.
1980
2007
Impl.forEachDistinctName(constant,
1981
2008
[&](ImportedName newName,
1982
2009
ImportNameVersion nameVersion) -> bool {
@@ -2027,6 +2054,19 @@ namespace {
2027
2054
}
2028
2055
}
2029
2056
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
+
2030
2070
return result;
2031
2071
}
2032
2072
0 commit comments