123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements the ExternalASTMerger, which vends a combination of
- // ASTs from several different ASTContext/FileManager pairs
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/ExternalASTMerger.h"
- using namespace clang;
- namespace {
- template <typename T> struct Source {
- T t;
- Source(T &&t) : t(std::move(t)) {}
- operator T() { return t; }
- template <typename U = T> U &get() { return t; }
- template <typename U = T> const U &get() const { return t; }
- template <typename U> operator Source<U>() { return Source<U>(t); }
- };
- typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
- class LazyASTImporter : public ASTImporter {
- public:
- LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
- ASTContext &FromContext, FileManager &FromFileManager)
- : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
- /*MinimalImport=*/true) {}
- Decl *Imported(Decl *From, Decl *To) override {
- if (auto ToTag = dyn_cast<TagDecl>(To)) {
- ToTag->setHasExternalLexicalStorage();
- } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
- ToNamespace->setHasExternalVisibleStorage();
- }
- return ASTImporter::Imported(From, To);
- }
- };
- Source<const DeclContext *>
- LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
- ASTImporter &ReverseImporter) {
- if (DC->isTranslationUnit()) {
- return SourceTU;
- }
- Source<const DeclContext *> SourceParentDC =
- LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
- if (!SourceParentDC) {
- // If we couldn't find the parent DC in this TranslationUnit, give up.
- return nullptr;
- }
- auto ND = cast<NamedDecl>(DC);
- DeclarationName Name = ND->getDeclName();
- Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
- DeclContext::lookup_result SearchResult =
- SourceParentDC.get()->lookup(SourceName.get());
- size_t SearchResultSize = SearchResult.size();
- // Handle multiple candidates once we have a test for it.
- // This may turn up when we import template specializations correctly.
- assert(SearchResultSize < 2);
- if (SearchResultSize == 0) {
- // couldn't find the name, so we have to give up
- return nullptr;
- } else {
- NamedDecl *SearchResultDecl = SearchResult[0];
- return dyn_cast<DeclContext>(SearchResultDecl);
- }
- }
- bool IsForwardDeclaration(Decl *D) {
- assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
- if (auto TD = dyn_cast<TagDecl>(D)) {
- return !TD->isThisDeclarationADefinition();
- } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
- return !FD->isThisDeclarationADefinition();
- } else {
- return false;
- }
- }
- void ForEachMatchingDC(
- const DeclContext *DC,
- llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
- std::function<void(const ExternalASTMerger::ImporterPair &IP,
- Source<const DeclContext *> SourceDC)>
- Callback) {
- for (const ExternalASTMerger::ImporterPair &IP : Importers) {
- Source<TranslationUnitDecl *> SourceTU(
- IP.Forward->getFromContext().getTranslationUnitDecl());
- Source<const DeclContext *> SourceDC =
- LookupSameContext(SourceTU, DC, *IP.Reverse);
- if (SourceDC.get()) {
- Callback(IP, SourceDC);
- }
- }
- }
- bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
- return std::any_of(Decls.begin(), Decls.end(), [&C](const Candidate &D) {
- return C.first.get()->getKind() == D.first.get()->getKind();
- });
- }
- } // end namespace
- ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
- llvm::ArrayRef<ImporterEndpoint> Sources) {
- for (const ImporterEndpoint &S : Sources) {
- Importers.push_back(
- {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
- llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
- /*MinimalImport=*/true)});
- }
- }
- bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
- DeclarationName Name) {
- llvm::SmallVector<NamedDecl *, 1> Decls;
- llvm::SmallVector<Candidate, 4> CompleteDecls;
- llvm::SmallVector<Candidate, 4> ForwardDecls;
- auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
- if (IsForwardDeclaration(C.first.get())) {
- if (!HasDeclOfSameType(ForwardDecls, C)) {
- ForwardDecls.push_back(C);
- }
- } else {
- CompleteDecls.push_back(C);
- }
- };
- ForEachMatchingDC(DC, Importers, [Name, &FilterFoundDecl](
- const ImporterPair &IP,
- Source<const DeclContext *> SourceDC) {
- DeclarationName FromName = IP.Reverse->Import(Name);
- DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
- for (NamedDecl *FromD : Result) {
- FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
- }
- });
- llvm::ArrayRef<Candidate> DeclsToReport =
- CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
- if (DeclsToReport.empty()) {
- return false;
- }
- Decls.reserve(DeclsToReport.size());
- for (const Candidate &C : DeclsToReport) {
- NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
- assert(d);
- Decls.push_back(d);
- }
- SetExternalVisibleDeclsForName(DC, Name, Decls);
- return true;
- }
- void ExternalASTMerger::FindExternalLexicalDecls(
- const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
- SmallVectorImpl<Decl *> &Result) {
- ForEachMatchingDC(
- DC, Importers, [DC, IsKindWeWant](const ImporterPair &IP,
- Source<const DeclContext *> SourceDC) {
- for (const Decl *SourceDecl : SourceDC.get()->decls()) {
- if (IsKindWeWant(SourceDecl->getKind())) {
- Decl *ImportedDecl =
- IP.Forward->Import(const_cast<Decl *>(SourceDecl));
- assert(ImportedDecl->getDeclContext() == DC);
- }
- }
- });
- }
|