Skip to content

Commit c41535a

Browse files
committed
Clang importer: start computing the effective lookup context with the name.
This places enumerators that will become either cases of a Swift enum or options in a Swift option into the context of the C enum type for the name lookup table.
1 parent 28dea3b commit c41535a

File tree

6 files changed

+54
-25
lines changed

6 files changed

+54
-25
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -706,10 +706,8 @@ void ClangImporter::Implementation::addEntryToLookupTable(
706706
SwiftLookupTable &table, clang::NamedDecl *named)
707707
{
708708
// If we have a name to import as, add this entry to the table.
709-
if (DeclName name = importFullName(named)) {
710-
clang::DeclContext *effectiveContext
711-
= named->getDeclContext()->getRedeclContext() ->getPrimaryContext();
712-
709+
clang::DeclContext *effectiveContext;
710+
if (DeclName name = importFullName(named, nullptr, &effectiveContext)) {
713711
table.addEntry(name, named, effectiveContext);
714712
}
715713

@@ -1353,15 +1351,46 @@ static DeclName parseDeclName(ASTContext &ctx, StringRef Name) {
13531351

13541352
DeclName ClangImporter::Implementation::importFullName(
13551353
const clang::NamedDecl *D,
1356-
bool &hasCustomName) {
1354+
bool *hasCustomName,
1355+
clang::DeclContext **effectiveContext) {
1356+
// Compute the effective context, if requested.
1357+
if (effectiveContext) {
1358+
auto dc = const_cast<clang::DeclContext *>(D->getDeclContext());
1359+
1360+
// Enumerators can end up within their enclosing enum or in the global
1361+
// scope, depending how their enclosing enumeration is imported.
1362+
if (isa<clang::EnumConstantDecl>(D)) {
1363+
auto enumDecl = cast<clang::EnumDecl>(dc);
1364+
switch (classifyEnum(enumDecl)) {
1365+
case EnumKind::Enum:
1366+
case EnumKind::Options:
1367+
// Enums are mapped to Swift enums, Options to Swift option sets.
1368+
*effectiveContext = enumDecl;
1369+
break;
1370+
1371+
case EnumKind::Constants:
1372+
case EnumKind::Unknown:
1373+
// The enum constant goes into the redeclaration context of the
1374+
// enum.
1375+
*effectiveContext = enumDecl->getRedeclContext();
1376+
break;
1377+
}
1378+
} else {
1379+
// Everything else goes into its redeclaration context.
1380+
*effectiveContext = dc->getRedeclContext();
1381+
}
1382+
}
1383+
13571384
// If we have a swift_name attribute, use that.
13581385
if (auto *nameAttr = D->getAttr<clang::SwiftNameAttr>()) {
1359-
hasCustomName = true;
1386+
if (hasCustomName)
1387+
*hasCustomName = true;
13601388
return parseDeclName(SwiftContext, nameAttr->getName());
13611389
}
13621390

13631391
// We don't have a customized name.
1364-
hasCustomName = false;
1392+
if (hasCustomName)
1393+
*hasCustomName = false;
13651394

13661395
// For empty names, there is nothing to do.
13671396
if (D->getDeclName().isEmpty()) return { };

lib/ClangImporter/ImportDecl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,7 +2720,7 @@ namespace {
27202720

27212721
// Determine the name of the function.
27222722
bool hasCustomName;
2723-
DeclName name = Impl.importFullName(decl, hasCustomName);
2723+
DeclName name = Impl.importFullName(decl, &hasCustomName);
27242724
if (!name)
27252725
return nullptr;
27262726

@@ -3014,7 +3014,7 @@ namespace {
30143014
switch (Impl.getFactoryAsInit(objcClass, decl)) {
30153015
case FactoryAsInitKind::AsInitializer:
30163016
if (decl->hasAttr<clang::SwiftNameAttr>()) {
3017-
initName = Impl.importFullName(decl, hasCustomName);
3017+
initName = Impl.importFullName(decl, &hasCustomName);
30183018
break;
30193019
}
30203020
// FIXME: We probably should stop using this codepath. It won't ever
@@ -3126,7 +3126,7 @@ namespace {
31263126
bool hasCustomName;
31273127
if (auto *customNameAttr = decl->getAttr<clang::SwiftNameAttr>()) {
31283128
if (!customNameAttr->getName().startswith("init(")) {
3129-
name = Impl.importFullName(decl, hasCustomName);
3129+
name = Impl.importFullName(decl, &hasCustomName);
31303130
}
31313131
}
31323132
if (!name) {

lib/ClangImporter/ImporterImpl.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -726,17 +726,19 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
726726
///
727727
/// Note that this may result in a name very different from the Clang name,
728728
/// so it should not be used when referencing Clang symbols.
729-
DeclName importFullName(const clang::NamedDecl *D) {
730-
bool hasCustomName;
731-
return importFullName(D, hasCustomName);
732-
}
733-
734-
/// Imports the full name of the given Clang declaration into Swift.
735729
///
736-
/// Note that this may result in a name very different from the Clang name,
737-
/// so it should not be used when referencing Clang symbols.
730+
/// \param D The Clang declaration whose name should be imported.
731+
///
732+
/// \param hasCustomName If non-null, will be set to indicate whether the
733+
/// name was provided directly via a C swift_name attribute.
734+
///
735+
/// \param effectiveContext If non-null, will be set to the effective
736+
/// Clang declaration context in which the declaration will be imported.
737+
/// This can differ from D's redeclaration context when the Clang importer
738+
/// introduces nesting, e.g., for enumerators within an NS_ENUM.
738739
DeclName importFullName(const clang::NamedDecl *D,
739-
bool &hasCustomName);
740+
bool *hasCustomName = nullptr,
741+
clang::DeclContext **effectiveContext = nullptr);
740742

741743
/// Imports the name of the given Clang decl into Swift.
742744
///

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) {
5353

5454
void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl,
5555
clang::DeclContext *effectiveContext) {
56-
clang::DeclContext *context
57-
= decl->getDeclContext()->getRedeclContext()->getPrimaryContext();
56+
clang::DeclContext *context = effectiveContext->getPrimaryContext();
5857

5958
// First, check whether there is already a full name entry.
6059
auto knownFull = FullNameTable.find(name);

test/IDE/dump_swift_lookup_tables.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@
2424
// CHECK-NEXT: Point:
2525
// CHECK-NEXT: TU: SNPoint
2626
// CHECK-NEXT: Rouge:
27-
// CHECK-NEXT: TU: SNColorRed
27+
// CHECK-NEXT: SNColorChoice: SNColorRed
2828
// CHECK-NEXT: SNColorBlue:
29-
// CHECK-NEXT: TU: SNColorBlue
29+
// CHECK-NEXT: SNColorChoice: SNColorBlue
3030
// CHECK-NEXT: SNColorChoice:
3131
// CHECK-NEXT: TU: SNColorChoice, SNColorChoice
3232
// CHECK-NEXT: SNColorGreen:
33-
// CHECK-NEXT: TU: SNColorGreen
33+
// CHECK-NEXT: SNColorChoice: SNColorGreen
3434
// CHECK-NEXT: SomeStruct:
3535
// CHECK-NEXT: TU: SNSomeStruct
3636
// CHECK-NEXT: __SNTransposeInPlace:

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,6 @@ static int doDumpAPI(const CompilerInvocation &InitInvok,
953953

954954
static int doDumpImporterLookupTables(const CompilerInvocation &InitInvok,
955955
StringRef SourceFilename) {
956-
auto &FEOpts = InitInvok.getFrontendOptions();
957956
if (options::ImportObjCHeader.empty()) {
958957
llvm::errs() << "implicit header required\n";
959958
llvm::cl::PrintHelpMessage();

0 commit comments

Comments
 (0)