mirror of
https://github.com/apple/swift.git
synced 2026-03-04 18:24:35 +01:00
[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:
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user