Skip to content

Commit 940a65a

Browse files
committed
[Clang importer] Make the "effective context" a core part of ImportedName.
Previously, the "effective context" parameter to importFullName was used only during the construction of Swift name lookup tables, so we can associate each declaration with a context. Expand the role of "effective context" so it is always a part of ImportedName and is also used by importDecl when actually importing the enum declaration. This is partially a cleanup, and partially staging for SE-0033, which will require this functionality more broadly.
1 parent c9d496b commit 940a65a

File tree

5 files changed

+146
-98
lines changed

5 files changed

+146
-98
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -715,20 +715,18 @@ void ClangImporter::Implementation::addEntryToLookupTable(
715715
if (shouldSuppressDeclImport(named)) return;
716716

717717
// If we have a name to import as, add this entry to the table.
718-
clang::DeclContext *effectiveContext;
719-
if (auto importedName = importFullName(named, None, &effectiveContext,
720-
&clangSema)) {
721-
table.addEntry(importedName.Imported, named, effectiveContext);
718+
if (auto importedName = importFullName(named, None, &clangSema)) {
719+
table.addEntry(importedName.Imported, named, importedName.EffectiveContext);
722720

723721
// Also add the alias, if needed.
724722
if (importedName.Alias)
725-
table.addEntry(importedName.Alias, named, effectiveContext);
723+
table.addEntry(importedName.Alias, named, importedName.EffectiveContext);
726724

727725
// Also add the subscript entry, if needed.
728726
if (importedName.IsSubscriptAccessor)
729727
table.addEntry(DeclName(SwiftContext, SwiftContext.Id_subscript,
730728
ArrayRef<Identifier>()),
731-
named, effectiveContext);
729+
named, importedName.EffectiveContext);
732730
} else if (auto category = dyn_cast<clang::ObjCCategoryDecl>(named)) {
733731
table.addCategory(category);
734732
}
@@ -1914,7 +1912,6 @@ namespace {
19141912
auto ClangImporter::Implementation::importFullName(
19151913
const clang::NamedDecl *D,
19161914
ImportNameOptions options,
1917-
clang::DeclContext **effectiveContext,
19181915
clang::Sema *clangSemaOverride) -> ImportedName {
19191916
clang::Sema &clangSema = clangSemaOverride ? *clangSemaOverride
19201917
: getClangSema();
@@ -1925,38 +1922,38 @@ auto ClangImporter::Implementation::importFullName(
19251922
if (isa<clang::ObjCCategoryDecl>(D))
19261923
return result;
19271924

1928-
// Compute the effective context, if requested.
1929-
if (effectiveContext) {
1930-
auto dc = const_cast<clang::DeclContext *>(D->getDeclContext());
1931-
1932-
// Enumerators can end up within their enclosing enum or in the global
1933-
// scope, depending how their enclosing enumeration is imported.
1934-
if (isa<clang::EnumConstantDecl>(D)) {
1935-
auto enumDecl = cast<clang::EnumDecl>(dc);
1936-
switch (getEnumKind(enumDecl, &clangSema.getPreprocessor())) {
1937-
case EnumKind::Enum:
1938-
case EnumKind::Options:
1939-
// Enums are mapped to Swift enums, Options to Swift option sets.
1940-
*effectiveContext = enumDecl;
1941-
break;
1925+
// Compute the effective context.
1926+
auto dc = const_cast<clang::DeclContext *>(D->getDeclContext());
19421927

1943-
case EnumKind::Constants:
1944-
case EnumKind::Unknown:
1945-
// The enum constant goes into the redeclaration context of the
1946-
// enum.
1947-
*effectiveContext = enumDecl->getRedeclContext();
1948-
break;
1949-
}
1950-
} else {
1951-
// Everything else goes into its redeclaration context.
1952-
*effectiveContext = dc->getRedeclContext();
1953-
}
1928+
// Enumerators can end up within their enclosing enum or in the global
1929+
// scope, depending how their enclosing enumeration is imported.
1930+
if (isa<clang::EnumConstantDecl>(D)) {
1931+
auto enumDecl = cast<clang::EnumDecl>(dc);
1932+
switch (getEnumKind(enumDecl, &clangSema.getPreprocessor())) {
1933+
case EnumKind::Enum:
1934+
case EnumKind::Options:
1935+
// Enums are mapped to Swift enums, Options to Swift option sets.
1936+
result.EffectiveContext = cast<clang::DeclContext>(enumDecl);
1937+
break;
19541938

1955-
// Anything in an Objective-C category or extension is adjusted to the
1956-
// class context.
1957-
if (auto category = dyn_cast<clang::ObjCCategoryDecl>(*effectiveContext)) {
1958-
*effectiveContext = category->getClassInterface();
1939+
case EnumKind::Constants:
1940+
case EnumKind::Unknown:
1941+
// The enum constant goes into the redeclaration context of the
1942+
// enum.
1943+
result.EffectiveContext = enumDecl->getRedeclContext();
1944+
break;
19591945
}
1946+
} else {
1947+
// Everything else goes into its redeclaration context.
1948+
result.EffectiveContext = dc->getRedeclContext();
1949+
}
1950+
1951+
// Anything in an Objective-C category or extension is adjusted to the
1952+
// class context.
1953+
if (auto category = dyn_cast_or_null<clang::ObjCCategoryDecl>(
1954+
result.EffectiveContext
1955+
.dyn_cast<clang::DeclContext *>())) {
1956+
result.EffectiveContext = category->getClassInterface();
19601957
}
19611958

19621959
// When omitting needless words, find the original method/property
@@ -1971,7 +1968,7 @@ auto ClangImporter::Implementation::importFullName(
19711968
method->getOverriddenMethods(overriddenMethods);
19721969
for (auto overridden : overriddenMethods) {
19731970
const auto overriddenName = importFullName(overridden, options,
1974-
nullptr,clangSemaOverride);
1971+
clangSemaOverride);
19751972
if (overriddenName.Imported)
19761973
overriddenNames.push_back({overridden, overriddenName});
19771974
}
@@ -1980,6 +1977,7 @@ auto ClangImporter::Implementation::importFullName(
19801977
if (!overriddenNames.empty()) {
19811978
if (overriddenNames.size() > 1)
19821979
mergeOverriddenNames(SwiftContext, method, overriddenNames);
1980+
overriddenNames[0].second.EffectiveContext = result.EffectiveContext;
19831981
return overriddenNames[0].second;
19841982
}
19851983
} else if (auto property = dyn_cast<clang::ObjCPropertyDecl>(D)) {
@@ -2001,7 +1999,6 @@ auto ClangImporter::Implementation::importFullName(
20011999

20022000
const auto overriddenName = importFullName(overriddenProperty,
20032001
options,
2004-
nullptr,
20052002
clangSemaOverride);
20062003
if (overriddenName.Imported)
20072004
overriddenNames.push_back({overriddenProperty, overriddenName});
@@ -2011,6 +2008,7 @@ auto ClangImporter::Implementation::importFullName(
20112008
if (!overriddenNames.empty()) {
20122009
if (overriddenNames.size() > 1)
20132010
mergeOverriddenNames(SwiftContext, property, overriddenNames);
2011+
overriddenNames[0].second.EffectiveContext = result.EffectiveContext;
20142012
return overriddenNames[0].second;
20152013
}
20162014
}

lib/ClangImporter/ImportDecl.cpp

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,7 +1440,8 @@ namespace {
14401440
// 'typedef const void *FooRef;' as CF types if they have the
14411441
// right attributes or match our name whitelist.
14421442
if (!SwiftType) {
1443-
auto DC = Impl.importDeclContextOf(Decl);
1443+
auto DC = Impl.importDeclContextOf(Decl,
1444+
importedName.EffectiveContext);
14441445
if (!DC)
14451446
return nullptr;
14461447

@@ -1566,7 +1567,7 @@ namespace {
15661567
}
15671568
}
15681569

1569-
auto DC = Impl.importDeclContextOf(Decl);
1570+
auto DC = Impl.importDeclContextOf(Decl, importedName.EffectiveContext);
15701571
if (!DC)
15711572
return nullptr;
15721573

@@ -2417,7 +2418,10 @@ namespace {
24172418
Decl *VisitEnumConstantDecl(const clang::EnumConstantDecl *decl) {
24182419
auto clangEnum = cast<clang::EnumDecl>(decl->getDeclContext());
24192420

2420-
auto name = Impl.importFullName(decl).Imported.getBaseName();
2421+
auto importedName = Impl.importFullName(decl);
2422+
if (!importedName) return nullptr;
2423+
2424+
auto name = importedName.Imported.getBaseName();
24212425
if (name.empty())
24222426
return nullptr;
24232427

@@ -2427,7 +2431,7 @@ namespace {
24272431
// constant with that integral type.
24282432

24292433
// The context where the constant will be introduced.
2430-
auto dc = Impl.importDeclContextOf(clangEnum);
2434+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
24312435
if (!dc)
24322436
return nullptr;
24332437

@@ -2458,7 +2462,8 @@ namespace {
24582462
// The enumeration was mapped to a struct containing the integral
24592463
// type. Create a constant with that struct type.
24602464

2461-
auto dc = Impl.importDeclContextOf(clangEnum);
2465+
// The context where the constant will be introduced.
2466+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
24622467
if (!dc)
24632468
return nullptr;
24642469

@@ -2490,6 +2495,9 @@ namespace {
24902495
// The enumeration was mapped to a high-level Swift type, and its
24912496
// elements were created as children of that enum. They aren't available
24922497
// independently.
2498+
2499+
// FIXME: This is gross. We shouldn't have to import
2500+
// everything to get at the individual constants.
24932501
return nullptr;
24942502
}
24952503
}
@@ -2512,11 +2520,12 @@ namespace {
25122520
return nullptr;
25132521
}
25142522
}
2515-
auto name = Impl.importFullName(decl).Imported.getBaseName();
2516-
if (name.empty())
2517-
return nullptr;
2523+
auto importedName = Impl.importFullName(decl);
2524+
if (!importedName) return nullptr;
25182525

2519-
auto dc = Impl.importDeclContextOf(decl);
2526+
auto name = importedName.Imported.getBaseName();
2527+
2528+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
25202529
if (!dc)
25212530
return nullptr;
25222531

@@ -2536,15 +2545,15 @@ namespace {
25362545
}
25372546

25382547
Decl *VisitFunctionDecl(const clang::FunctionDecl *decl) {
2539-
auto dc = Impl.importDeclContextOf(decl);
2540-
if (!dc)
2541-
return nullptr;
2542-
25432548
// Determine the name of the function.
25442549
auto importedName = Impl.importFullName(decl);
25452550
if (!importedName)
25462551
return nullptr;
25472552

2553+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
2554+
if (!dc)
2555+
return nullptr;
2556+
25482557
DeclName name = importedName.Imported;
25492558
bool hasCustomName = importedName.HasCustomName;
25502559

@@ -2607,11 +2616,12 @@ namespace {
26072616

26082617
Decl *VisitFieldDecl(const clang::FieldDecl *decl) {
26092618
// Fields are imported as variables.
2610-
auto name = Impl.importFullName(decl).Imported.getBaseName();
2611-
if (name.empty())
2612-
return nullptr;
2619+
auto importedName = Impl.importFullName(decl);
2620+
if (!importedName) return nullptr;
26132621

2614-
auto dc = Impl.importDeclContextOf(decl);
2622+
auto name = importedName.Imported.getBaseName();
2623+
2624+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
26152625
if (!dc)
26162626
return nullptr;
26172627

@@ -2653,11 +2663,12 @@ namespace {
26532663
return nullptr;
26542664

26552665
// Variables are imported as... variables.
2656-
auto name = Impl.importFullName(decl).Imported.getBaseName();
2657-
if (name.empty())
2658-
return nullptr;
2666+
auto importedName = Impl.importFullName(decl);
2667+
if (!importedName) return nullptr;
26592668

2660-
auto dc = Impl.importDeclContextOf(decl);
2669+
auto name = importedName.Imported.getBaseName();
2670+
2671+
auto dc = Impl.importDeclContextOf(decl, importedName.EffectiveContext);
26612672
if (!dc)
26622673
return nullptr;
26632674

@@ -5576,17 +5587,26 @@ DeclContext *ClangImporter::Implementation::importDeclContextImpl(
55765587
}
55775588

55785589
DeclContext *
5579-
ClangImporter::Implementation::importDeclContextOf(const clang::Decl *D) {
5580-
const clang::DeclContext *DC = D->getDeclContext();
5590+
ClangImporter::Implementation::importDeclContextOf(
5591+
const clang::Decl *D,
5592+
EffectiveClangContext context)
5593+
{
5594+
if (const clang::DeclContext *dc = context.dyn_cast<clang::DeclContext *>()) {
5595+
if (dc->isTranslationUnit()) {
5596+
if (auto *M = getClangModuleForDecl(D))
5597+
return M;
5598+
else
5599+
return nullptr;
5600+
}
55815601

5582-
if (DC->isTranslationUnit()) {
5583-
if (auto *M = getClangModuleForDecl(D))
5584-
return M;
5585-
else
5586-
return nullptr;
5602+
return importDeclContextImpl(dc);
55875603
}
55885604

5589-
return importDeclContextImpl(DC);
5605+
// Import the typedef-name as a declaration.
5606+
auto decl = importDecl(context.get<clang::TypedefNameDecl *>());
5607+
if (!decl) return nullptr;
5608+
5609+
return cast_or_null<DeclContext>(decl);
55905610
}
55915611

55925612
ValueDecl *

lib/ClangImporter/ImporterImpl.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,16 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
817817
/// For an initializer, the kind of initializer to import.
818818
CtorInitializerKind InitKind = CtorInitializerKind::Designated;
819819

820+
/// The context into which this declaration will be imported.
821+
///
822+
/// When the context into which the declaration will be imported
823+
/// matches a Clang declaration context (the common case), the
824+
/// result will be expressed as a declaration contet. Otherwise,
825+
/// if the Clang type is not itself a declaration context (for
826+
/// example, a typedef that comes into Swift as a strong type),
827+
/// the type declaration will be provided.
828+
EffectiveClangContext EffectiveContext;
829+
820830
/// For names that map Objective-C error handling conventions into
821831
/// throwing Swift methods, describes how the mapping is performed.
822832
Optional<ImportedErrorInfo> ErrorInfo;
@@ -844,14 +854,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
844854
/// so it should not be used when referencing Clang symbols.
845855
///
846856
/// \param D The Clang declaration whose name should be imported.
847-
///
848-
/// \param effectiveContext If non-null, will be set to the effective
849-
/// Clang declaration context in which the declaration will be imported.
850-
/// This can differ from D's redeclaration context when the Clang importer
851-
/// introduces nesting, e.g., for enumerators within an NS_ENUM.
852857
ImportedName importFullName(const clang::NamedDecl *D,
853858
ImportNameOptions options = None,
854-
clang::DeclContext **effectiveContext = nullptr,
855859
clang::Sema *clangSemaOverride = nullptr);
856860

857861
/// Imports the name of the given Clang macro into Swift.
@@ -956,9 +960,19 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
956960
/// \brief Import the declaration context of a given Clang declaration into
957961
/// Swift.
958962
///
963+
/// \param context The effective context as determined by importFullName.
964+
///
959965
/// \returns The imported declaration context, or null if it could not
960966
/// be converted.
961-
DeclContext *importDeclContextOf(const clang::Decl *D);
967+
DeclContext *importDeclContextOf(const clang::Decl *D,
968+
EffectiveClangContext context);
969+
970+
/// \brief Import the declaration context of a given Clang
971+
/// declaration into Swift.
972+
DeclContext *importDeclContextOf(const clang::Decl *D) {
973+
return importDeclContextOf(
974+
D, const_cast<clang::DeclContext *>(D->getDeclContext()));
975+
}
962976

963977
/// \brief Create a new named constant with the given value.
964978
///

0 commit comments

Comments
 (0)