Files
swift-mirror/lib/AST/NameLookupRequests.cpp
John Hui 1341516dba [cxx-interop] Fix spurious ambiguous member lookup for eagerly imported members (#78673)
Follow-up from #78132, which did not fix issues related to eagerly imported members like subscripts.

This patch restructures recursive ClangRecordMemberLookup requests to importBaseMemberDecl() in the recursive calls, rather than propagating base member decls up to the initial lookup request and doing the import. Doing so seems to fix lingering resolution issues (which I've added to the regression tests).

rdar://141069984
2025-01-21 22:06:09 -08:00

686 lines
26 KiB
C++

//===--- NameLookupRequests.cpp - Name Lookup Requests --------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "swift/AST/NameLookupRequests.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Evaluator.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/PotentialMacroExpansions.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Assertions.h"
#include "swift/ClangImporter/ClangImporterRequests.h"
#include "swift/Subsystems.h"
using namespace swift;
namespace swift {
// Implement the name lookup type zone.
#define SWIFT_TYPEID_ZONE NameLookup
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
#include "swift/Basic/ImplementTypeIDZone.h"
#undef SWIFT_TYPEID_ZONE
#undef SWIFT_TYPEID_HEADER
}
//----------------------------------------------------------------------------//
// Referenced inherited decls computation.
//----------------------------------------------------------------------------//
SourceLoc InheritedDeclsReferencedRequest::getNearestLoc() const {
const auto &storage = getStorage();
auto inheritedTypes = InheritedTypes(std::get<0>(storage));
return inheritedTypes.getEntry(std::get<1>(storage)).getLoc();
}
//----------------------------------------------------------------------------//
// Superclass declaration computation.
//----------------------------------------------------------------------------//
void SuperclassDeclRequest::diagnoseCycle(DiagnosticEngine &diags) const {
// FIXME: Improve this diagnostic.
auto nominalDecl = std::get<0>(getStorage());
diags.diagnose(nominalDecl, diag::circular_class_inheritance,
nominalDecl->getName());
}
void SuperclassDeclRequest::noteCycleStep(DiagnosticEngine &diags) const {
auto decl = std::get<0>(getStorage());
diags.diagnose(decl, diag::kind_declname_declared_here,
decl->getDescriptiveKind(), decl->getName());
}
std::optional<ClassDecl *> SuperclassDeclRequest::getCachedResult() const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
if (classDecl->LazySemanticInfo.SuperclassDecl.getInt())
return classDecl->LazySemanticInfo.SuperclassDecl.getPointer();
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
if (protocolDecl->LazySemanticInfo.SuperclassDecl.getInt())
return protocolDecl->LazySemanticInfo.SuperclassDecl.getPointer();
return std::nullopt;
}
void SuperclassDeclRequest::cacheResult(ClassDecl *value) const {
auto nominalDecl = std::get<0>(getStorage());
if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
classDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
protocolDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
}
//----------------------------------------------------------------------------//
// InheritedProtocolsRequest computation.
//----------------------------------------------------------------------------//
std::optional<ArrayRef<ProtocolDecl *>>
InheritedProtocolsRequest::getCachedResult() const {
auto proto = std::get<0>(getStorage());
if (!proto->areInheritedProtocolsValid())
return std::nullopt;
return proto->InheritedProtocols;
}
void InheritedProtocolsRequest::cacheResult(ArrayRef<ProtocolDecl *> PDs) const {
auto proto = std::get<0>(getStorage());
proto->InheritedProtocols = PDs;
proto->setInheritedProtocolsValid();
}
void InheritedProtocolsRequest::writeDependencySink(
evaluator::DependencyCollector &tracker,
ArrayRef<ProtocolDecl *> PDs) const {
for (auto *parentProto : PDs) {
tracker.addPotentialMember(parentProto);
}
}
//----------------------------------------------------------------------------//
// AllInheritedProtocolsRequest computation.
//----------------------------------------------------------------------------//
std::optional<ArrayRef<ProtocolDecl *>>
AllInheritedProtocolsRequest::getCachedResult() const {
auto proto = std::get<0>(getStorage());
if (!proto->areAllInheritedProtocolsValid())
return std::nullopt;
return proto->AllInheritedProtocols;
}
void AllInheritedProtocolsRequest::cacheResult(ArrayRef<ProtocolDecl *> PDs) const {
auto proto = std::get<0>(getStorage());
proto->AllInheritedProtocols = PDs;
proto->setAllInheritedProtocolsValid();
}
//----------------------------------------------------------------------------//
// ProtocolRequirementsRequest computation.
//----------------------------------------------------------------------------//
std::optional<ArrayRef<ValueDecl *>>
ProtocolRequirementsRequest::getCachedResult() const {
auto proto = std::get<0>(getStorage());
if (!proto->areProtocolRequirementsValid())
return std::nullopt;
return proto->ProtocolRequirements;
}
void ProtocolRequirementsRequest::cacheResult(ArrayRef<ValueDecl *> PDs) const {
auto proto = std::get<0>(getStorage());
proto->ProtocolRequirements = PDs;
proto->setProtocolRequirementsValid();
}
//----------------------------------------------------------------------------//
// Missing designated initializers computation
//----------------------------------------------------------------------------//
std::optional<bool>
HasMissingDesignatedInitializersRequest::getCachedResult() const {
auto classDecl = std::get<0>(getStorage());
return classDecl->getCachedHasMissingDesignatedInitializers();
}
void HasMissingDesignatedInitializersRequest::cacheResult(bool result) const {
auto classDecl = std::get<0>(getStorage());
classDecl->setHasMissingDesignatedInitializers(result);
}
bool
HasMissingDesignatedInitializersRequest::evaluate(Evaluator &evaluator,
ClassDecl *subject) const {
// Short-circuit and check for the attribute here.
if (subject->getAttrs().hasAttribute<HasMissingDesignatedInitializersAttr>())
return true;
AccessScope scope =
subject->getFormalAccessScope(/*useDC*/nullptr,
/*treatUsableFromInlineAsPublic*/true);
// This flag only makes sense for public types that will be written in the
// module.
if (!scope.isPublic())
return false;
// Make sure any implicit constructors are synthesized.
(void)evaluateOrDefault(
evaluator,
ResolveImplicitMemberRequest{subject,
ImplicitMemberAction::ResolveImplicitInit},
{});
auto constructors = subject->lookupDirect(DeclBaseName::createConstructor());
return llvm::any_of(constructors, [&](ValueDecl *decl) {
auto init = cast<ConstructorDecl>(decl);
if (!init->isDesignatedInit())
return false;
AccessScope scope =
init->getFormalAccessScope(/*useDC*/nullptr,
/*treatUsableFromInlineAsPublic*/true);
return !scope.isPublic();
});
}
//----------------------------------------------------------------------------//
// Extended nominal computation.
//----------------------------------------------------------------------------//
std::optional<NominalTypeDecl *>
ExtendedNominalRequest::getCachedResult() const {
// Note: if we fail to compute any nominal declaration, it's considered
// a cache miss. This allows us to recompute the extended nominal types
// during extension binding.
// This recomputation is also what allows you to extend types defined inside
// other extensions, regardless of source file order. See \c bindExtensions(),
// which uses a worklist algorithm that attempts to bind everything until
// fixed point.
auto ext = std::get<0>(getStorage());
if (!ext->hasBeenBound() || !ext->getExtendedNominal())
return std::nullopt;
return ext->getExtendedNominal();
}
void ExtendedNominalRequest::cacheResult(NominalTypeDecl *value) const {
auto ext = std::get<0>(getStorage());
ext->setExtendedNominal(value);
}
void ExtendedNominalRequest::writeDependencySink(
evaluator::DependencyCollector &tracker,
NominalTypeDecl *value) const {
if (!value)
return;
// Ensure this extension comes from a source file.
auto *SF = std::get<0>(getStorage())->getParentSourceFile();
if (!SF)
return;
tracker.addPotentialMember(value);
}
//----------------------------------------------------------------------------//
// Destructor computation.
//----------------------------------------------------------------------------//
std::optional<DestructorDecl *> GetDestructorRequest::getCachedResult() const {
auto *classDecl = std::get<0>(getStorage());
auto results = classDecl->lookupDirect(DeclBaseName::createDestructor());
if (results.empty())
return std::nullopt;
return cast<DestructorDecl>(results.front());
}
void GetDestructorRequest::cacheResult(DestructorDecl *value) const {
auto *classDecl = std::get<0>(getStorage());
classDecl->getImplementationContext()->addMember(value);
}
//----------------------------------------------------------------------------//
// GenericParamListRequest computation.
//----------------------------------------------------------------------------//
std::optional<GenericParamList *>
GenericParamListRequest::getCachedResult() const {
using GenericParamsState = GenericContext::GenericParamsState;
auto *decl = std::get<0>(getStorage());
switch (decl->GenericParamsAndState.getInt()) {
case GenericParamsState::TypeChecked:
case GenericParamsState::ParsedAndTypeChecked:
return decl->GenericParamsAndState.getPointer();
case GenericParamsState::Parsed:
return std::nullopt;
}
}
void GenericParamListRequest::cacheResult(GenericParamList *params) const {
using GenericParamsState = GenericContext::GenericParamsState;
auto *context = std::get<0>(getStorage());
if (params)
params->setDeclContext(context);
assert(context->GenericParamsAndState.getInt() == GenericParamsState::Parsed);
bool hadParsedGenericParams =
context->GenericParamsAndState.getPointer() != nullptr;
auto newState = hadParsedGenericParams
? GenericParamsState::ParsedAndTypeChecked
: GenericParamsState::TypeChecked;
context->GenericParamsAndState.setPointerAndInt(params, newState);
}
//----------------------------------------------------------------------------//
// UnqualifiedLookupRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const UnqualifiedLookupDescriptor &desc) {
out << "looking up ";
simple_display(out, desc.Name);
out << " from ";
simple_display(out, desc.DC);
out << " with options ";
simple_display(out, desc.Options);
}
SourceLoc
swift::extractNearestSourceLoc(const UnqualifiedLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.DC);
}
//----------------------------------------------------------------------------//
// DirectLookupRequest computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
const DirectLookupDescriptor &desc) {
out << "directly looking up ";
simple_display(out, desc.Name);
out << " on ";
simple_display(out, desc.DC);
out << " with options ";
simple_display(out, desc.Options);
}
SourceLoc swift::extractNearestSourceLoc(const DirectLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.DC);
}
//----------------------------------------------------------------------------//
// LookupOperatorRequest computation.
//----------------------------------------------------------------------------//
OperatorLookupDescriptor OperatorLookupDescriptor::forDC(const DeclContext *DC,
Identifier name) {
auto *moduleDC = DC->getModuleScopeContext();
if (auto *file = dyn_cast<FileUnit>(moduleDC)) {
return OperatorLookupDescriptor::forFile(file, name);
} else {
auto *mod = cast<ModuleDecl>(moduleDC->getAsDecl());
return OperatorLookupDescriptor::forModule(mod, name);
}
}
ArrayRef<FileUnit *> OperatorLookupDescriptor::getFiles() const {
if (auto *module = getModule())
return module->getFiles();
// Return an ArrayRef pointing to the FileUnit in the union.
return llvm::ArrayRef(*fileOrModule.getAddrOfPtr1());
}
void swift::simple_display(llvm::raw_ostream &out,
const OperatorLookupDescriptor &desc) {
out << "looking up operator ";
simple_display(out, desc.name);
out << " in ";
simple_display(out, desc.fileOrModule);
}
SourceLoc swift::extractNearestSourceLoc(const OperatorLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.fileOrModule);
}
void DirectLookupRequest::writeDependencySink(
evaluator::DependencyCollector &tracker,
const TinyPtrVector<ValueDecl *> &result) const {
auto &desc = std::get<0>(getStorage());
// Add used members from the perspective of
// 1) The decl context they are found in
// 2) The decl context of the request
// This gets us a dependency not just on `Foo.bar` but on `extension Foo.bar`.
for (const auto *member : result) {
tracker.addUsedMember(member->getDeclContext(), desc.Name.getBaseName());
}
tracker.addUsedMember(desc.DC, desc.Name.getBaseName());
}
//----------------------------------------------------------------------------//
// LookupInModuleRequest computation.
//----------------------------------------------------------------------------//
void LookupInModuleRequest::writeDependencySink(
evaluator::DependencyCollector &reqTracker,
const QualifiedLookupResult &l) const {
auto *DC = std::get<0>(getStorage());
auto member = std::get<1>(getStorage());
// Decline to record lookups if the module in question has no incremental
// dependency information available.
auto *module = DC->getParentModule();
if (module->isMainModule() || module->hasIncrementalInfo()) {
reqTracker.addTopLevelName(member.getBaseName());
}
}
void swift::simple_display(llvm::raw_ostream &out,
const LookupConformanceDescriptor &desc) {
out << "looking up conformance to ";
simple_display(out, desc.PD);
out << " for ";
out << desc.Ty.getString();
}
//----------------------------------------------------------------------------//
// AnyObjectLookupRequest computation.
//----------------------------------------------------------------------------//
void AnyObjectLookupRequest::writeDependencySink(
evaluator::DependencyCollector &reqTracker,
const QualifiedLookupResult &l) const {
auto member = std::get<1>(getStorage());
reqTracker.addDynamicLookupName(member.getBaseName());
}
SourceLoc
swift::extractNearestSourceLoc(const LookupConformanceDescriptor &desc) {
return SourceLoc();
}
//----------------------------------------------------------------------------//
// ModuleQualifiedLookupRequest computation.
//----------------------------------------------------------------------------//
void ModuleQualifiedLookupRequest::writeDependencySink(
evaluator::DependencyCollector &reqTracker,
const QualifiedLookupResult &l) const {
auto *module = std::get<1>(getStorage());
auto member = std::get<2>(getStorage());
// Decline to record lookups if the module in question has no incremental
// dependency information available.
if (module->isMainModule() || module->hasIncrementalInfo()) {
reqTracker.addTopLevelName(member.getBaseName());
}
}
//----------------------------------------------------------------------------//
// LookupConformanceInModuleRequest computation.
//----------------------------------------------------------------------------//
void LookupConformanceInModuleRequest::writeDependencySink(
evaluator::DependencyCollector &reqTracker,
ProtocolConformanceRef lookupResult) const {
if (lookupResult.isInvalid() || !lookupResult.isConcrete())
return;
auto &desc = std::get<0>(getStorage());
auto *Adoptee = desc.Ty->getAnyNominal();
if (!Adoptee)
return;
// Decline to record lookups if the module in question has no incremental
// dependency information available.
auto *conformance = lookupResult.getConcrete();
auto *module = conformance->getDeclContext()->getParentModule();
if (module->isMainModule() || module->hasIncrementalInfo()) {
reqTracker.addPotentialMember(Adoptee);
}
}
//----------------------------------------------------------------------------//
// UnqualifiedLookupRequest computation.
//----------------------------------------------------------------------------//
void UnqualifiedLookupRequest::writeDependencySink(
evaluator::DependencyCollector &track,
const LookupResult &res) const {
auto &desc = std::get<0>(getStorage());
track.addTopLevelName(desc.Name.getBaseName());
}
//----------------------------------------------------------------------------//
// SPIGroupsRequest computation.
//----------------------------------------------------------------------------//
std::optional<llvm::ArrayRef<Identifier>> SPIGroupsRequest::getCachedResult() const {
auto *decl = std::get<0>(getStorage());
if (decl->hasNoSPIGroups())
return ArrayRef<Identifier>();
return decl->getASTContext().evaluator.getCachedNonEmptyOutput(*this);
}
void SPIGroupsRequest::cacheResult(llvm::ArrayRef<Identifier> result) const {
auto *decl = std::get<0>(getStorage());
if (result.empty()) {
const_cast<Decl *>(decl)->setHasNoSPIGroups();
return;
}
decl->getASTContext().evaluator.cacheNonEmptyOutput(*this, std::move(result));
}
// 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);
if (desc.recordDecl != desc.inheritingDecl)
out << " inherited by ";
simple_display(out, desc.inheritingDecl);
}
SourceLoc
swift::extractNearestSourceLoc(const ClangRecordMemberLookupDescriptor &desc) {
return extractNearestSourceLoc(desc.recordDecl);
}
//----------------------------------------------------------------------------//
// CustomRefCountingOperation computation.
//----------------------------------------------------------------------------//
void swift::simple_display(llvm::raw_ostream &out,
CustomRefCountingOperationDescriptor desc) {
out << "Finding custom (foreign reference) reference counting operation '"
<< (desc.kind == CustomRefCountingOperationKind::retain ? "retain"
: "release")
<< "' for '" << desc.decl->getNameStr() << "'.\n";
}
SourceLoc
swift::extractNearestSourceLoc(CustomRefCountingOperationDescriptor desc) {
return SourceLoc();
}
//----------------------------------------------------------------------------//
// Macro-related adjustments to name lookup requests.
//----------------------------------------------------------------------------//
//
// Macros introduced a significant wrinkle into Swift's name lookup mechanism.
// Specifically, when resolving names (and, really, anything else) within the
// arguments to a macro expansion, name lookup must not try to expand any
// macros, because doing so trivially creates a cyclic dependency amongst the
// macro expansions that will be detected by the request-evaluator.
//
// We use source locations to answer the question "is this part of an argument
// to a macro?" through `namelookup::isInMacroArgument`. If the answer is yes,
// then we adjust the options used for the name lookup request we are forming
// to exclude macro expansions. The evaluation of that request will then avoid
// expanding any macros, and not produce any results that involve entries in
// already-expanded macros. By adjusting the request itself, we still
// distinguish between requests that can and cannot look into macro expansions,
// so it doesn't break caching for those immediate requests.
/// Exclude macros in the unqualified lookup descriptor if we need to.
static UnqualifiedLookupDescriptor contextualizeOptions(
UnqualifiedLookupDescriptor descriptor) {
if (!descriptor.Options.contains(
UnqualifiedLookupFlags::ExcludeMacroExpansions)
&& namelookup::isInMacroArgument(
descriptor.DC->getParentSourceFile(), descriptor.Loc))
descriptor.Options |= UnqualifiedLookupFlags::ExcludeMacroExpansions;
if (!descriptor.Options.contains(UnqualifiedLookupFlags::ABIProviding)
&& namelookup::isInABIAttr(
descriptor.DC->getParentSourceFile(), descriptor.Loc))
descriptor.Options |= UnqualifiedLookupFlags::ABIProviding;
return descriptor;
}
/// Exclude macros in the direct lookup descriptor if we need to.
static DirectLookupDescriptor contextualizeOptions(
DirectLookupDescriptor descriptor, SourceLoc loc) {
if (!descriptor.Options.contains(
NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions)
&& namelookup::isInMacroArgument(
descriptor.DC->getParentSourceFile(), loc))
descriptor.Options |=
NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions;
if (!descriptor.Options.contains(
NominalTypeDecl::LookupDirectFlags::ABIProviding)
&& namelookup::isInABIAttr(
descriptor.DC->getParentSourceFile(), loc))
descriptor.Options |=
NominalTypeDecl::LookupDirectFlags::ABIProviding;
return descriptor;
}
/// Exclude macros in the name lookup options if we need to.
static NLOptions
contextualizeOptions(const DeclContext *dc, SourceLoc loc,
NLOptions options) {
if (!(options & NL_ExcludeMacroExpansions)
&& namelookup::isInMacroArgument(dc->getParentSourceFile(), loc))
options |= NL_ExcludeMacroExpansions;
if (!(options & NL_ABIProviding)
&& namelookup::isInABIAttr(dc->getParentSourceFile(), loc))
options |= NL_ABIProviding;
return options;
}
UnqualifiedLookupRequest::UnqualifiedLookupRequest(
UnqualifiedLookupDescriptor descriptor
) : SimpleRequest(contextualizeOptions(descriptor)) { }
LookupInModuleRequest::LookupInModuleRequest(
const DeclContext *moduleOrFile, DeclName name, NLKind lookupKind,
namelookup::ResolutionKind resolutionKind,
const DeclContext *moduleScopeContext,
SourceLoc loc, NLOptions options
) : SimpleRequest(moduleOrFile, name, lookupKind, resolutionKind,
moduleScopeContext,
contextualizeOptions(moduleOrFile, loc, options)) { }
ModuleQualifiedLookupRequest::ModuleQualifiedLookupRequest(
const DeclContext *dc, ModuleDecl *module, DeclNameRef name,
SourceLoc loc, NLOptions options
) : SimpleRequest(dc, module, name,
contextualizeOptions(dc, loc, options)) { }
QualifiedLookupRequest::QualifiedLookupRequest(
const DeclContext *dc,
SmallVector<NominalTypeDecl *, 4> decls,
DeclNameRef name,
SourceLoc loc, NLOptions options
) : SimpleRequest(dc, std::move(decls), name,
contextualizeOptions(dc, loc, options)) { }
DirectLookupRequest::DirectLookupRequest(DirectLookupDescriptor descriptor, SourceLoc loc)
: SimpleRequest(contextualizeOptions(descriptor, loc)) { }
// 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) \
reinterpret_cast<AbstractRequestFunction *>(&Name::evaluateRequest),
#include "swift/AST/NameLookupTypeIDZone.def"
#undef SWIFT_REQUEST
};
void swift::registerNameLookupRequestFunctions(Evaluator &evaluator) {
evaluator.registerRequestFunctions(Zone::NameLookup,
nameLookupRequestFunctions);
}