diff --git a/lib/ClangImporter/SwiftLookupTable.cpp b/lib/ClangImporter/SwiftLookupTable.cpp index c234ee2cf3d..533607142b9 100644 --- a/lib/ClangImporter/SwiftLookupTable.cpp +++ b/lib/ClangImporter/SwiftLookupTable.cpp @@ -19,28 +19,6 @@ #include "clang/AST/DeclObjC.h" using namespace swift; -bool SwiftLookupTable::matchesContext(clang::DeclContext *foundContext, - clang::DeclContext *requestedContext) { - /// If the requested context was null, we match. - if (!requestedContext) - return true; - - // If the contexts match, we match. - if (foundContext == requestedContext) - return true; - - // If we found something in an Objective-C protocol to which a class - // conforms, we match. - if (auto objcProto = dyn_cast(foundContext)) { - if (auto objcClass = dyn_cast(requestedContext)) { - return objcClass->ClassImplementsProtocol(objcProto, - /*lookupCategory=*/true); - } - } - - return false; -} - /// Determine whether the new declarations matches an existing declaration. static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) { // If the canonical declarations are equivalent, we have a match. @@ -51,9 +29,38 @@ static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) { return false; } +Optional> +SwiftLookupTable::translateContext(clang::DeclContext *context) { + // Translation unit context. + if (context->isTranslationUnit()) + return std::make_pair(ContextKind::TranslationUnit, StringRef()); + + // Tag declaration context. + if (auto tag = dyn_cast(context)) { + if (tag->getIdentifier()) + return std::make_pair(ContextKind::Tag, tag->getName()); + if (auto typedefDecl = tag->getTypedefNameForAnonDecl()) + return std::make_pair(ContextKind::Tag, typedefDecl->getName()); + return None; + } + + // Objective-C class context. + if (auto objcClass = dyn_cast(context)) + return std::make_pair(ContextKind::ObjCClass, objcClass->getName()); + + // Objective-C protocol context. + if (auto objcProtocol = dyn_cast(context)) + return std::make_pair(ContextKind::ObjCProtocol, objcProtocol->getName()); + + return None; +} + void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl, clang::DeclContext *effectiveContext) { - clang::DeclContext *context = effectiveContext->getPrimaryContext(); + // Translate the context. + auto contextOpt = translateContext(effectiveContext); + if (!contextOpt) return; + auto context = *contextOpt; // First, check whether there is already a full name entry. auto knownFull = FullNameTable.find(name); @@ -86,7 +93,7 @@ void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl, // This is a new context for this name. Add it. FullTableEntry newEntry; - newEntry.Context = context; + newEntry.Context = context;; newEntry.Decls.push_back(decl); fullEntries.push_back(newEntry); } @@ -181,13 +188,15 @@ void SwiftLookupTable::dump() const { llvm::errs() << " " << fullName << ":\n"; const auto &fullEntries = FullNameTable.find(fullName)->second; for (const auto &fullEntry : fullEntries) { - llvm::errs() << " "; - if (fullEntry.Context->isTranslationUnit()) { + switch (fullEntry.Context.first) { + case ContextKind::TranslationUnit: llvm::errs() << "TU"; - } else if (auto named = dyn_cast(fullEntry.Context)) { - printName(named, llvm::errs()); - } else { - llvm::errs() << ""; + break; + + case ContextKind::Tag: + case ContextKind::ObjCClass: + case ContextKind::ObjCProtocol: + llvm::errs() << fullEntry.Context.second; } llvm::errs() << ": "; diff --git a/lib/ClangImporter/SwiftLookupTable.h b/lib/ClangImporter/SwiftLookupTable.h index 59ec0a120bc..4f4a0d4a6f9 100644 --- a/lib/ClangImporter/SwiftLookupTable.h +++ b/lib/ClangImporter/SwiftLookupTable.h @@ -20,8 +20,10 @@ #include "swift/Basic/LLVM.h" #include "swift/AST/Identifier.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" +#include namespace clang { class NamedDecl; @@ -40,20 +42,32 @@ namespace swift { /// entities based on their Swift names, and is used by the Clang /// importer to satisfy the Swift compiler's queries. class SwiftLookupTable { +public: + /// The kind of context in which a name occurs. + enum class ContextKind : uint8_t { + /// A translation unit. + TranslationUnit = 0, + /// A tag declaration (struct, enum, union, C++ class). + Tag, + /// An Objective-C class. + ObjCClass, + /// An Objective-C protocol. + ObjCProtocol, + }; + /// An entry in the table of C entities indexed by full Swift name. struct FullTableEntry { /// The context in which the entities with the given name occur, e.g., /// a class, struct, translation unit, etc. - /// - /// Many Clang DeclContexts can have redeclarations, so this entry /// is always the canonical DeclContext for the entity. - clang::DeclContext *Context; + std::pair Context; /// The set of Clang declarations with this name and in this /// context. llvm::TinyPtrVector Decls; }; +private: /// A table mapping from the full name of Swift entities to all of /// the C entities that have that name, in all contexts. llvm::DenseMap> FullNameTable; @@ -62,11 +76,11 @@ class SwiftLookupTable { /// full Swift names based on that identifier. llvm::DenseMap> BaseNameTable; - /// Determine whether the given context we found matches the - /// requested context. - bool matchesContext(clang::DeclContext *foundContext, - clang::DeclContext *requestedContext); public: + /// Translate a Clang DeclContext into a context kind and name. + llvm::Optional> + translateContext(clang::DeclContext *context); + /// Add an entry to the lookup table. /// /// \param name The Swift name of the entry.