Skip to content

Commit

Permalink
Clang importer: start computing the effective lookup context with the…
Browse files Browse the repository at this point in the history
… 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.
  • Loading branch information
DougGregor committed Dec 3, 2015
1 parent 28dea3b commit c41535a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 25 deletions.
43 changes: 36 additions & 7 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,10 +706,8 @@ void ClangImporter::Implementation::addEntryToLookupTable(
SwiftLookupTable &table, clang::NamedDecl *named)
{
// If we have a name to import as, add this entry to the table.
if (DeclName name = importFullName(named)) {
clang::DeclContext *effectiveContext
= named->getDeclContext()->getRedeclContext() ->getPrimaryContext();

clang::DeclContext *effectiveContext;
if (DeclName name = importFullName(named, nullptr, &effectiveContext)) {
table.addEntry(name, named, effectiveContext);
}

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

DeclName ClangImporter::Implementation::importFullName(
const clang::NamedDecl *D,
bool &hasCustomName) {
bool *hasCustomName,
clang::DeclContext **effectiveContext) {
// Compute the effective context, if requested.
if (effectiveContext) {
auto dc = const_cast<clang::DeclContext *>(D->getDeclContext());

// Enumerators can end up within their enclosing enum or in the global
// scope, depending how their enclosing enumeration is imported.
if (isa<clang::EnumConstantDecl>(D)) {
auto enumDecl = cast<clang::EnumDecl>(dc);
switch (classifyEnum(enumDecl)) {
case EnumKind::Enum:
case EnumKind::Options:
// Enums are mapped to Swift enums, Options to Swift option sets.
*effectiveContext = enumDecl;
break;

case EnumKind::Constants:
case EnumKind::Unknown:
// The enum constant goes into the redeclaration context of the
// enum.
*effectiveContext = enumDecl->getRedeclContext();
break;
}
} else {
// Everything else goes into its redeclaration context.
*effectiveContext = dc->getRedeclContext();
}
}

// If we have a swift_name attribute, use that.
if (auto *nameAttr = D->getAttr<clang::SwiftNameAttr>()) {
hasCustomName = true;
if (hasCustomName)
*hasCustomName = true;
return parseDeclName(SwiftContext, nameAttr->getName());
}

// We don't have a customized name.
hasCustomName = false;
if (hasCustomName)
*hasCustomName = false;

// For empty names, there is nothing to do.
if (D->getDeclName().isEmpty()) return { };
Expand Down
6 changes: 3 additions & 3 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2720,7 +2720,7 @@ namespace {

// Determine the name of the function.
bool hasCustomName;
DeclName name = Impl.importFullName(decl, hasCustomName);
DeclName name = Impl.importFullName(decl, &hasCustomName);
if (!name)
return nullptr;

Expand Down Expand Up @@ -3014,7 +3014,7 @@ namespace {
switch (Impl.getFactoryAsInit(objcClass, decl)) {
case FactoryAsInitKind::AsInitializer:
if (decl->hasAttr<clang::SwiftNameAttr>()) {
initName = Impl.importFullName(decl, hasCustomName);
initName = Impl.importFullName(decl, &hasCustomName);
break;
}
// FIXME: We probably should stop using this codepath. It won't ever
Expand Down Expand Up @@ -3126,7 +3126,7 @@ namespace {
bool hasCustomName;
if (auto *customNameAttr = decl->getAttr<clang::SwiftNameAttr>()) {
if (!customNameAttr->getName().startswith("init(")) {
name = Impl.importFullName(decl, hasCustomName);
name = Impl.importFullName(decl, &hasCustomName);
}
}
if (!name) {
Expand Down
20 changes: 11 additions & 9 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,17 +726,19 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
///
/// Note that this may result in a name very different from the Clang name,
/// so it should not be used when referencing Clang symbols.
DeclName importFullName(const clang::NamedDecl *D) {
bool hasCustomName;
return importFullName(D, hasCustomName);
}

/// Imports the full name of the given Clang declaration into Swift.
///
/// Note that this may result in a name very different from the Clang name,
/// so it should not be used when referencing Clang symbols.
/// \param D The Clang declaration whose name should be imported.
///
/// \param hasCustomName If non-null, will be set to indicate whether the
/// name was provided directly via a C swift_name attribute.
///
/// \param effectiveContext If non-null, will be set to the effective
/// Clang declaration context in which the declaration will be imported.
/// This can differ from D's redeclaration context when the Clang importer
/// introduces nesting, e.g., for enumerators within an NS_ENUM.
DeclName importFullName(const clang::NamedDecl *D,
bool &hasCustomName);
bool *hasCustomName = nullptr,
clang::DeclContext **effectiveContext = nullptr);

/// Imports the name of the given Clang decl into Swift.
///
Expand Down
3 changes: 1 addition & 2 deletions lib/ClangImporter/SwiftLookupTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) {

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

// First, check whether there is already a full name entry.
auto knownFull = FullNameTable.find(name);
Expand Down
6 changes: 3 additions & 3 deletions test/IDE/dump_swift_lookup_tables.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
// CHECK-NEXT: Point:
// CHECK-NEXT: TU: SNPoint
// CHECK-NEXT: Rouge:
// CHECK-NEXT: TU: SNColorRed
// CHECK-NEXT: SNColorChoice: SNColorRed
// CHECK-NEXT: SNColorBlue:
// CHECK-NEXT: TU: SNColorBlue
// CHECK-NEXT: SNColorChoice: SNColorBlue
// CHECK-NEXT: SNColorChoice:
// CHECK-NEXT: TU: SNColorChoice, SNColorChoice
// CHECK-NEXT: SNColorGreen:
// CHECK-NEXT: TU: SNColorGreen
// CHECK-NEXT: SNColorChoice: SNColorGreen
// CHECK-NEXT: SomeStruct:
// CHECK-NEXT: TU: SNSomeStruct
// CHECK-NEXT: __SNTransposeInPlace:
Expand Down
1 change: 0 additions & 1 deletion tools/swift-ide-test/swift-ide-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,6 @@ static int doDumpAPI(const CompilerInvocation &InitInvok,

static int doDumpImporterLookupTables(const CompilerInvocation &InitInvok,
StringRef SourceFilename) {
auto &FEOpts = InitInvok.getFrontendOptions();
if (options::ImportObjCHeader.empty()) {
llvm::errs() << "implicit header required\n";
llvm::cl::PrintHelpMessage();
Expand Down

0 comments on commit c41535a

Please sign in to comment.