mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Swift lookup tables: translate DeclContext into something less tied to the AST.
We want to serialize this data structure, so make that easier.
This commit is contained in:
@@ -19,28 +19,6 @@
|
|||||||
#include "clang/AST/DeclObjC.h"
|
#include "clang/AST/DeclObjC.h"
|
||||||
using namespace swift;
|
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<clang::ObjCProtocolDecl>(foundContext)) {
|
|
||||||
if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(requestedContext)) {
|
|
||||||
return objcClass->ClassImplementsProtocol(objcProto,
|
|
||||||
/*lookupCategory=*/true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determine whether the new declarations matches an existing declaration.
|
/// Determine whether the new declarations matches an existing declaration.
|
||||||
static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) {
|
static bool matchesExistingDecl(clang::Decl *decl, clang::Decl *existingDecl) {
|
||||||
// If the canonical declarations are equivalent, we have a match.
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<std::pair<SwiftLookupTable::ContextKind, StringRef>>
|
||||||
|
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<clang::TagDecl>(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<clang::ObjCInterfaceDecl>(context))
|
||||||
|
return std::make_pair(ContextKind::ObjCClass, objcClass->getName());
|
||||||
|
|
||||||
|
// Objective-C protocol context.
|
||||||
|
if (auto objcProtocol = dyn_cast<clang::ObjCProtocolDecl>(context))
|
||||||
|
return std::make_pair(ContextKind::ObjCProtocol, objcProtocol->getName());
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl,
|
void SwiftLookupTable::addEntry(DeclName name, clang::NamedDecl *decl,
|
||||||
clang::DeclContext *effectiveContext) {
|
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.
|
// First, check whether there is already a full name entry.
|
||||||
auto knownFull = FullNameTable.find(name);
|
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.
|
// This is a new context for this name. Add it.
|
||||||
FullTableEntry newEntry;
|
FullTableEntry newEntry;
|
||||||
newEntry.Context = context;
|
newEntry.Context = context;;
|
||||||
newEntry.Decls.push_back(decl);
|
newEntry.Decls.push_back(decl);
|
||||||
fullEntries.push_back(newEntry);
|
fullEntries.push_back(newEntry);
|
||||||
}
|
}
|
||||||
@@ -181,13 +188,15 @@ void SwiftLookupTable::dump() const {
|
|||||||
llvm::errs() << " " << fullName << ":\n";
|
llvm::errs() << " " << fullName << ":\n";
|
||||||
const auto &fullEntries = FullNameTable.find(fullName)->second;
|
const auto &fullEntries = FullNameTable.find(fullName)->second;
|
||||||
for (const auto &fullEntry : fullEntries) {
|
for (const auto &fullEntry : fullEntries) {
|
||||||
llvm::errs() << " ";
|
switch (fullEntry.Context.first) {
|
||||||
if (fullEntry.Context->isTranslationUnit()) {
|
case ContextKind::TranslationUnit:
|
||||||
llvm::errs() << "TU";
|
llvm::errs() << "TU";
|
||||||
} else if (auto named = dyn_cast<clang::NamedDecl>(fullEntry.Context)) {
|
break;
|
||||||
printName(named, llvm::errs());
|
|
||||||
} else {
|
case ContextKind::Tag:
|
||||||
llvm::errs() << "<unknown>";
|
case ContextKind::ObjCClass:
|
||||||
|
case ContextKind::ObjCProtocol:
|
||||||
|
llvm::errs() << fullEntry.Context.second;
|
||||||
}
|
}
|
||||||
llvm::errs() << ": ";
|
llvm::errs() << ": ";
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
#include "swift/Basic/LLVM.h"
|
#include "swift/Basic/LLVM.h"
|
||||||
#include "swift/AST/Identifier.h"
|
#include "swift/AST/Identifier.h"
|
||||||
#include "llvm/ADT/DenseMap.h"
|
#include "llvm/ADT/DenseMap.h"
|
||||||
|
#include "llvm/ADT/Optional.h"
|
||||||
#include "llvm/ADT/SmallVector.h"
|
#include "llvm/ADT/SmallVector.h"
|
||||||
#include "llvm/ADT/TinyPtrVector.h"
|
#include "llvm/ADT/TinyPtrVector.h"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
class NamedDecl;
|
class NamedDecl;
|
||||||
@@ -40,20 +42,32 @@ namespace swift {
|
|||||||
/// entities based on their Swift names, and is used by the Clang
|
/// entities based on their Swift names, and is used by the Clang
|
||||||
/// importer to satisfy the Swift compiler's queries.
|
/// importer to satisfy the Swift compiler's queries.
|
||||||
class SwiftLookupTable {
|
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.
|
/// An entry in the table of C entities indexed by full Swift name.
|
||||||
struct FullTableEntry {
|
struct FullTableEntry {
|
||||||
/// The context in which the entities with the given name occur, e.g.,
|
/// The context in which the entities with the given name occur, e.g.,
|
||||||
/// a class, struct, translation unit, etc.
|
/// a class, struct, translation unit, etc.
|
||||||
///
|
|
||||||
/// Many Clang DeclContexts can have redeclarations, so this entry
|
|
||||||
/// is always the canonical DeclContext for the entity.
|
/// is always the canonical DeclContext for the entity.
|
||||||
clang::DeclContext *Context;
|
std::pair<ContextKind, StringRef> Context;
|
||||||
|
|
||||||
/// The set of Clang declarations with this name and in this
|
/// The set of Clang declarations with this name and in this
|
||||||
/// context.
|
/// context.
|
||||||
llvm::TinyPtrVector<clang::NamedDecl *> Decls;
|
llvm::TinyPtrVector<clang::NamedDecl *> Decls;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
/// A table mapping from the full name of Swift entities to all of
|
/// A table mapping from the full name of Swift entities to all of
|
||||||
/// the C entities that have that name, in all contexts.
|
/// the C entities that have that name, in all contexts.
|
||||||
llvm::DenseMap<DeclName, SmallVector<FullTableEntry, 2>> FullNameTable;
|
llvm::DenseMap<DeclName, SmallVector<FullTableEntry, 2>> FullNameTable;
|
||||||
@@ -62,11 +76,11 @@ class SwiftLookupTable {
|
|||||||
/// full Swift names based on that identifier.
|
/// full Swift names based on that identifier.
|
||||||
llvm::DenseMap<Identifier, SmallVector<DeclName, 2>> BaseNameTable;
|
llvm::DenseMap<Identifier, SmallVector<DeclName, 2>> BaseNameTable;
|
||||||
|
|
||||||
/// Determine whether the given context we found matches the
|
|
||||||
/// requested context.
|
|
||||||
bool matchesContext(clang::DeclContext *foundContext,
|
|
||||||
clang::DeclContext *requestedContext);
|
|
||||||
public:
|
public:
|
||||||
|
/// Translate a Clang DeclContext into a context kind and name.
|
||||||
|
llvm::Optional<std::pair<ContextKind, StringRef>>
|
||||||
|
translateContext(clang::DeclContext *context);
|
||||||
|
|
||||||
/// Add an entry to the lookup table.
|
/// Add an entry to the lookup table.
|
||||||
///
|
///
|
||||||
/// \param name The Swift name of the entry.
|
/// \param name The Swift name of the entry.
|
||||||
|
|||||||
Reference in New Issue
Block a user