blob: 8b635d1ce5ed6327304f3cd36d9d8d235c274b35 [file] [log] [blame]
//===--- DWARFImporter.cpp - Import Clang modules from DWARF --------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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 "ImporterImpl.h"
#include "swift/AST/ImportCache.h"
#include "swift/AST/Module.h"
using namespace swift;
void DWARFImporterDelegate::anchor() {}
/// Represents a Clang module that was "imported" from debug info. Since all the
/// loading of types is done on demand, this class is effectively empty.
class DWARFModuleUnit final : public LoadedFile {
ClangImporter::Implementation &Owner;
public:
DWARFModuleUnit(ModuleDecl &M, ClangImporter::Implementation &owner)
: LoadedFile(FileUnitKind::DWARFModule, M), Owner(owner) {}
virtual bool isSystemModule() const override { return false; }
/// Forwards the request to the ClangImporter, which forwards it to the
/// DWARFimporterDelegate.
virtual void
lookupValue(DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl *> &results) const override {
Owner.lookupValueDWARF(name, lookupKind,
getParentModule()->getName(), results);
}
virtual TypeDecl *
lookupNestedType(Identifier name,
const NominalTypeDecl *baseType) const override {
return nullptr;
}
virtual void lookupVisibleDecls(ImportPath::Access accessPath,
VisibleDeclConsumer &consumer,
NLKind lookupKind) const override {}
virtual void
lookupClassMembers(ImportPath::Access accessPath,
VisibleDeclConsumer &consumer) const override {}
virtual void
lookupClassMember(ImportPath::Access accessPath, DeclName name,
SmallVectorImpl<ValueDecl *> &decls) const override {}
void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const override {}
virtual void
getTopLevelDecls(SmallVectorImpl<Decl *> &results) const override {}
virtual void
getDisplayDecls(SmallVectorImpl<Decl *> &results) const override {}
virtual void
getImportedModules(SmallVectorImpl<ImportedModule> &imports,
ModuleDecl::ImportFilter filter) const override {}
virtual void getImportedModulesForLookup(
SmallVectorImpl<ImportedModule> &imports) const override {};
virtual void collectLinkLibraries(
ModuleDecl::LinkLibraryCallback callback) const override {};
Identifier
getDiscriminatorForPrivateValue(const ValueDecl *D) const override {
llvm_unreachable("no private decls in Clang modules");
}
virtual StringRef getFilename() const override { return ""; }
virtual const clang::Module *getUnderlyingClangModule() const override {
return nullptr;
}
static bool classof(const FileUnit *file) {
return file->getKind() == FileUnitKind::DWARFModule;
}
static bool classof(const DeclContext *DC) {
return isa<FileUnit>(DC) && classof(cast<FileUnit>(DC));
}
};
static_assert(IsTriviallyDestructible<DWARFModuleUnit>::value,
"DWARFModuleUnits are BumpPtrAllocated; the d'tor is not called");
ModuleDecl *ClangImporter::Implementation::loadModuleDWARF(
SourceLoc importLoc, ImportPath::Module path) {
// There's no importing from debug info if no importer is installed.
if (!DWARFImporter)
return nullptr;
// FIXME: Implement submodule support!
Identifier name = path[0].Item;
auto it = DWARFModuleUnits.find(name);
if (it != DWARFModuleUnits.end())
return it->second->getParentModule();
auto *decl = ModuleDecl::create(name, SwiftContext);
decl->setIsNonSwiftModule();
decl->setHasResolvedImports();
auto *wrapperUnit = new (SwiftContext) DWARFModuleUnit(*decl, *this);
DWARFModuleUnits.insert({name, wrapperUnit});
decl->addFile(*wrapperUnit);
// Force load overlay modules for all imported modules.
assert(namelookup::getAllImports(decl).size() == 1 &&
namelookup::getAllImports(decl).front().importedModule == decl &&
"DWARF module depends on additional modules?");
// Register the module with the ASTContext so it is available for lookups.
if (!SwiftContext.getLoadedModule(name))
SwiftContext.addLoadedModule(decl);
return decl;
}
// This function exists to defeat the lazy member importing mechanism. The
// DWARFImporter is not capable of loading individual members, so it cannot
// benefit from this optimization yet anyhow. Besides, if you're importing a
// type here, you more than likely want to dump it and its fields. Loading all
// members populates lookup tables in the Clang Importer and ensures the
// absence of cache-fill-related side effects.
static void forceLoadAllMembers(IterableDeclContext *IDC) {
if (!IDC) return;
IDC->loadAllMembers();
}
void ClangImporter::Implementation::lookupValueDWARF(
DeclName name, NLKind lookupKind, Identifier inModule,
SmallVectorImpl<ValueDecl *> &results) {
if (lookupKind != NLKind::QualifiedLookup)
return;
if (!DWARFImporter)
return;
SmallVector<clang::Decl *, 4> decls;
DWARFImporter->lookupValue(name.getBaseIdentifier().str(), None,
inModule.str(), decls);
for (auto *clangDecl : decls) {
auto *namedDecl = dyn_cast<clang::NamedDecl>(clangDecl);
if (!namedDecl)
continue;
auto *swiftDecl = cast_or_null<ValueDecl>(
importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion));
if (!swiftDecl)
continue;
if (swiftDecl->getName().matchesRef(name) &&
swiftDecl->getDeclContext()->isModuleScopeContext()) {
forceLoadAllMembers(dyn_cast<IterableDeclContext>(swiftDecl));
results.push_back(swiftDecl);
}
}
}
void ClangImporter::Implementation::lookupTypeDeclDWARF(
StringRef rawName, ClangTypeKind kind,
llvm::function_ref<void(TypeDecl *)> receiver) {
if (!DWARFImporter)
return;
/// This function is invoked by ASTDemangler, which doesn't filter by module.
SmallVector<clang::Decl *, 1> decls;
DWARFImporter->lookupValue(rawName, kind, {}, decls);
for (auto *clangDecl : decls) {
if (!isa<clang::TypeDecl>(clangDecl) &&
!isa<clang::ObjCContainerDecl>(clangDecl) &&
!isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
continue;
}
auto *namedDecl = cast<clang::NamedDecl>(clangDecl);
Decl *importedDecl = cast_or_null<ValueDecl>(
importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion));
if (auto *importedType = dyn_cast_or_null<TypeDecl>(importedDecl)) {
forceLoadAllMembers(dyn_cast<IterableDeclContext>(importedType));
receiver(importedType);
}
}
}
void ClangImporter::setDWARFImporterDelegate(DWARFImporterDelegate &delegate) {
Impl.setDWARFImporterDelegate(delegate);
}
void ClangImporter::Implementation::setDWARFImporterDelegate(
DWARFImporterDelegate &delegate) {
DWARFImporter = &delegate;
}