[nfc][cxx-interop] Add three requests ClangDirectLookupRequest, CXXNamespaceMemberLookup, and ClangRecordMemberLookup.

None of these requests are used, so this is a non-functional change.
This commit is contained in:
zoecarver
2021-09-23 16:22:17 -07:00
parent 40422f021b
commit 0ca8dd364f
5 changed files with 361 additions and 1 deletions

View File

@@ -19,8 +19,161 @@
#include "swift/AST/SimpleRequest.h"
#include "swift/AST/ASTTypeIDs.h"
#include "swift/AST/EvaluatorDependencies.h"
#include "swift/AST/FileUnit.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/NameLookup.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/TinyPtrVector.h"
namespace swift {
class Decl;
class DeclName;
class EnumDecl;
/// The input type for a clang direct lookup request.
struct ClangDirectLookupDescriptor final {
Decl *decl;
DeclName name;
ClangDirectLookupDescriptor(Decl *decl, DeclName name)
: decl(decl), name(name) {}
friend llvm::hash_code hash_value(const ClangDirectLookupDescriptor &desc) {
return llvm::hash_combine(desc.name, desc.decl);
}
friend bool operator==(const ClangDirectLookupDescriptor &lhs,
const ClangDirectLookupDescriptor &rhs) {
return lhs.name == rhs.name && lhs.decl == rhs.decl;
}
friend bool operator!=(const ClangDirectLookupDescriptor &lhs,
const ClangDirectLookupDescriptor &rhs) {
return !(lhs == rhs);
}
};
void simple_display(llvm::raw_ostream &out,
const ClangDirectLookupDescriptor &desc);
SourceLoc extractNearestSourceLoc(const ClangDirectLookupDescriptor &desc);
/// This matches SwiftLookupTable::SingleEntry;
using SingleEntry = llvm::PointerUnion<clang::NamedDecl *, clang::MacroInfo *,
clang::ModuleMacro *>;
/// Uses the appropriate SwiftLookupTable to find a set of clang decls given
/// their name.
class ClangDirectLookupRequest
: public SimpleRequest<ClangDirectLookupRequest,
SmallVector<SingleEntry, 4>(
ClangDirectLookupDescriptor),
RequestFlags::Uncached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
SmallVector<SingleEntry, 4> evaluate(Evaluator &evaluator,
ClangDirectLookupDescriptor desc) const;
};
/// The input type for a namespace member lookup request.
struct CXXNamespaceMemberLookupDescriptor final {
EnumDecl *namespaceDecl;
DeclName name;
CXXNamespaceMemberLookupDescriptor(EnumDecl *namespaceDecl, DeclName name)
: namespaceDecl(namespaceDecl), name(name) {
assert(isa<clang::NamespaceDecl>(namespaceDecl->getClangDecl()));
}
friend llvm::hash_code
hash_value(const CXXNamespaceMemberLookupDescriptor &desc) {
return llvm::hash_combine(desc.name, desc.namespaceDecl);
}
friend bool operator==(const CXXNamespaceMemberLookupDescriptor &lhs,
const CXXNamespaceMemberLookupDescriptor &rhs) {
return lhs.name == rhs.name && lhs.namespaceDecl == rhs.namespaceDecl;
}
friend bool operator!=(const CXXNamespaceMemberLookupDescriptor &lhs,
const CXXNamespaceMemberLookupDescriptor &rhs) {
return !(lhs == rhs);
}
};
void simple_display(llvm::raw_ostream &out,
const CXXNamespaceMemberLookupDescriptor &desc);
SourceLoc
extractNearestSourceLoc(const CXXNamespaceMemberLookupDescriptor &desc);
/// Uses ClangDirectLookup to find a named member inside of the given namespace.
class CXXNamespaceMemberLookup
: public SimpleRequest<CXXNamespaceMemberLookup,
TinyPtrVector<ValueDecl *>(
CXXNamespaceMemberLookupDescriptor),
RequestFlags::Uncached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
TinyPtrVector<ValueDecl *>
evaluate(Evaluator &evaluator, CXXNamespaceMemberLookupDescriptor desc) const;
};
/// The input type for a record member lookup request.
struct ClangRecordMemberLookupDescriptor final {
StructDecl *recordDecl;
DeclName name;
ClangRecordMemberLookupDescriptor(StructDecl *recordDecl, DeclName name)
: recordDecl(recordDecl), name(name) {
assert(isa<clang::RecordDecl>(recordDecl->getClangDecl()));
}
friend llvm::hash_code
hash_value(const ClangRecordMemberLookupDescriptor &desc) {
return llvm::hash_combine(desc.name, desc.recordDecl);
}
friend bool operator==(const ClangRecordMemberLookupDescriptor &lhs,
const ClangRecordMemberLookupDescriptor &rhs) {
return lhs.name == rhs.name && lhs.recordDecl == rhs.recordDecl;
}
friend bool operator!=(const ClangRecordMemberLookupDescriptor &lhs,
const ClangRecordMemberLookupDescriptor &rhs) {
return !(lhs == rhs);
}
};
void simple_display(llvm::raw_ostream &out,
const ClangRecordMemberLookupDescriptor &desc);
SourceLoc
extractNearestSourceLoc(const ClangRecordMemberLookupDescriptor &desc);
/// Uses ClangDirectLookup to find a named member inside of the given record.
class ClangRecordMemberLookup
: public SimpleRequest<ClangRecordMemberLookup,
TinyPtrVector<ValueDecl *>(
ClangRecordMemberLookupDescriptor),
RequestFlags::Uncached> {
public:
using SimpleRequest::SimpleRequest;
private:
friend SimpleRequest;
// Evaluation.
TinyPtrVector<ValueDecl *>
evaluate(Evaluator &evaluator, ClangRecordMemberLookupDescriptor desc) const;
};
#define SWIFT_TYPEID_ZONE ClangImporter
#define SWIFT_TYPEID_HEADER "swift/ClangImporter/ClangImporterTypeIDZone.def"

View File

@@ -15,3 +15,12 @@
//
//===----------------------------------------------------------------------===//
SWIFT_REQUEST(ClangImporter, ClangDirectLookupRequest,
(SmallVector<SingleEntry, 4>(ClangDirectLookupDescriptor)), Uncached,
NoLocationInfo)
SWIFT_REQUEST(ClangImporter, CXXNamespaceMemberLookup,
Decl *(CXXNamespaceMemberLookupDescriptor), Uncached,
NoLocationInfo)
SWIFT_REQUEST(ClangImporter, ClangRecordMemberLookup,
Decl *(ClangRecordMemberLookupDescriptor), Uncached,
NoLocationInfo)

View File

@@ -412,6 +412,68 @@ void UnqualifiedLookupRequest::writeDependencySink(
track.addTopLevelName(desc.Name.getBaseName());
}
// The following clang importer requests have some definitions here to prevent
// linker errors when building lib syntax parser (which doesn't link with the
// clang importer).
//----------------------------------------------------------------------------//
// ClangDirectLookupRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const ClangDirectLookupDescriptor &desc) {
out << "Looking up ";
simple_display(out, desc.name);
out << " in ";
simple_display(out, desc.decl);
}
SourceLoc
swift::extractNearestSourceLoc(const ClangDirectLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.decl);
}
//----------------------------------------------------------------------------//
// CXXNamespaceMemberLookup computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const CXXNamespaceMemberLookupDescriptor &desc) {
out << "Looking up ";
simple_display(out, desc.name);
out << " in ";
simple_display(out, desc.namespaceDecl);
}
SourceLoc
swift::extractNearestSourceLoc(const CXXNamespaceMemberLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.namespaceDecl);
}
//----------------------------------------------------------------------------//
// ClangRecordMemberLookup computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const ClangRecordMemberLookupDescriptor &desc) {
out << "Looking up ";
simple_display(out, desc.name);
out << " in ";
simple_display(out, desc.recordDecl);
}
SourceLoc
swift::extractNearestSourceLoc(const ClangRecordMemberLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.recordDecl);
}
// Implement the clang importer type zone.
#define SWIFT_TYPEID_ZONE ClangImporter
#define SWIFT_TYPEID_HEADER "swift/ClangImporter/ClangImporterTypeIDZone.def"
#include "swift/Basic/ImplementTypeIDZone.h"
#undef SWIFT_TYPEID_ZONE
#undef SWIFT_TYPEID_HEADER
// Define request evaluation functions for each of the name lookup requests.
static AbstractRequestFunction *nameLookupRequestFunctions[] = {
#define SWIFT_REQUEST(Zone, Name, Sig, Caching, LocOptions) \

View File

@@ -26,12 +26,14 @@
#include "swift/AST/LinkLibrary.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/Range.h"
#include "swift/Basic/StringExtras.h"
#include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangImporterRequests.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Config.h"
#include "swift/Demangling/Demangle.h"
@@ -4017,6 +4019,141 @@ void ClangImporter::Implementation::lookupAllObjCMembers(
}
}
static SmallVector<SwiftLookupTable::SingleEntry, 4>
lookupInClassTemplateSpecialization(
ASTContext &ctx, const clang::ClassTemplateSpecializationDecl *clangDecl,
DeclName name) {
// TODO: we could make this faster if we can cache class templates in the
// lookup table as well.
// Import all the names to figure out which ones we're looking for.
SmallVector<SwiftLookupTable::SingleEntry, 4> found;
for (auto member : clangDecl->decls()) {
auto namedDecl = dyn_cast<clang::NamedDecl>(member);
if (!namedDecl)
continue;
auto memberName = ctx.getClangModuleLoader()->importName(namedDecl);
if (!memberName)
continue;
// Use the base names here because *sometimes* our input name won't have
// any arguments.
if (name.getBaseName().compare(memberName.getBaseName()) == 0)
found.push_back(namedDecl);
}
return found;
}
SmallVector<SwiftLookupTable::SingleEntry, 4>
ClangDirectLookupRequest::evaluate(Evaluator &evaluator,
ClangDirectLookupDescriptor desc) const {
auto &ctx = desc.decl->getASTContext();
auto *clangDecl = desc.decl->getClangDecl();
// Class templates aren't in the lookup table.
if (auto spec = dyn_cast<clang::ClassTemplateSpecializationDecl>(clangDecl))
return lookupInClassTemplateSpecialization(ctx, spec, desc.name);
auto *clangModule =
getClangOwningModule(clangDecl, clangDecl->getASTContext());
auto *lookupTable = ctx.getClangModuleLoader()->findLookupTable(clangModule);
auto *swiftDeclContext = desc.decl->getInnermostDeclContext();
auto *declContextTypeDecl = swiftDeclContext->getSelfNominalTypeDecl();
auto effectiveClangContext =
ctx.getClangModuleLoader()->getEffectiveClangContext(declContextTypeDecl);
auto foundDecls = lookupTable->lookup(
SerializedSwiftName(desc.name.getBaseName()), effectiveClangContext);
// TODO: in `SwiftLookupTable::lookup` the `searchContext` is only a string.
// This is problematic because we might have two nested search contexts with
// the same name. The search context needs to be updated to be a decl (or
// decl context), but that will be a larger, seperate refactor. When that
// happens we can remove the below logic.
//
// We filter here by ensuring that each decl and all of its parents have the
// same name as `clangDecl` and its parents. This is prefered to checking the
// decl context pointer is equal to `clangDecl` because we may have a forward
// declared struct, multiple redecls of a namespace, or transparent contexts.
auto deepCompareDeclContexts = [](auto first, auto second) {
while (first->getParent() && second->getParent()) {
first = first->getParent();
second = second->getParent();
// Look through transparent contexts. If we have one (or more) extern C++
// contexts, that is the same as none.
while (first->isTransparentContext())
first = first->getParent();
while (second->isTransparentContext())
second = second->getParent();
auto firstName = dyn_cast<clang::NamedDecl>(first);
auto secondName = dyn_cast<clang::NamedDecl>(second);
if (!firstName || !secondName) {
if (firstName != secondName)
return false;
continue;
}
if (firstName->getName() != secondName->getName())
return false;
}
return !first->getParent() && !second->getParent();
};
SmallVector<SwiftLookupTable::SingleEntry, 4> filteredDecls;
llvm::copy_if(
foundDecls, std::back_inserter(filteredDecls),
[&deepCompareDeclContexts, dc = cast<clang::DeclContext>(clangDecl)](
SwiftLookupTable::SingleEntry decl) {
return deepCompareDeclContexts(
decl.get<clang::NamedDecl *>()->getDeclContext(), dc);
});
return filteredDecls;
}
TinyPtrVector<ValueDecl *> CXXNamespaceMemberLookup::evaluate(
Evaluator &evaluator, CXXNamespaceMemberLookupDescriptor desc) const {
EnumDecl *namespaceDecl = desc.namespaceDecl;
DeclName name = desc.name;
auto &ctx = namespaceDecl->getASTContext();
auto allResults = evaluateOrDefault(
ctx.evaluator, ClangDirectLookupRequest({namespaceDecl, name}), {});
TinyPtrVector<ValueDecl *> result;
for (auto found : allResults) {
auto clangMember = found.get<clang::NamedDecl *>();
if (auto import =
ctx.getClangModuleLoader()->importDeclDirectly(clangMember))
result.push_back(cast<ValueDecl>(import));
}
return result;
}
TinyPtrVector<ValueDecl *> ClangRecordMemberLookup::evaluate(
Evaluator &evaluator, ClangRecordMemberLookupDescriptor desc) const {
StructDecl *recordDecl = desc.recordDecl;
DeclName name = desc.name;
auto &ctx = recordDecl->getASTContext();
auto allResults = evaluateOrDefault(
ctx.evaluator, ClangDirectLookupRequest({recordDecl, name}), {});
// Find the results that are actually a member of "recordDecl".
TinyPtrVector<ValueDecl *> result;
for (auto found : allResults) {
auto named = found.get<clang::NamedDecl *>();
if (dyn_cast<clang::Decl>(named->getDeclContext()) ==
recordDecl->getClangDecl())
if (auto import = ctx.getClangModuleLoader()->importDeclDirectly(named))
result.push_back(cast<ValueDecl>(import));
}
return result;
}
TinyPtrVector<ValueDecl *>
ClangImporter::Implementation::loadNamedMembers(
const IterableDeclContext *IDC, DeclBaseName N, uint64_t contextData) {

View File

@@ -23,7 +23,6 @@ using namespace swift;
// Define request evaluation functions for each of the name lookup requests.
static AbstractRequestFunction *clangImporterRequestFunctions[] = {
nullptr // TODO: remove this whenever a request is actually added.
#define SWIFT_REQUEST(Zone, Name, Sig, Caching, LocOptions) \
reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
#include "swift/ClangImporter/ClangImporterTypeIDZone.def"