1 //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ExternalASTMerger, which vends a combination of
11 // ASTs from several different ASTContext/FileManager pairs
13 //===----------------------------------------------------------------------===//
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/ExternalASTMerger.h"
20 using namespace clang;
24 template <typename T> struct Source {
27 operator T() { return t; }
28 template <typename U = T> U &get() { return t; }
29 template <typename U = T> const U &get() const { return t; }
30 template <typename U> operator Source<U>() { return Source<U>(t); }
33 typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
35 class LazyASTImporter : public ASTImporter {
37 LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
38 ASTContext &FromContext, FileManager &FromFileManager)
39 : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
40 /*MinimalImport=*/true) {}
41 Decl *Imported(Decl *From, Decl *To) override {
42 if (auto ToTag = dyn_cast<TagDecl>(To)) {
43 ToTag->setHasExternalLexicalStorage();
44 ToTag->setMustBuildLookupTable();
45 } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
46 ToNamespace->setHasExternalVisibleStorage();
48 return ASTImporter::Imported(From, To);
52 Source<const DeclContext *>
53 LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
54 ASTImporter &ReverseImporter) {
55 if (DC->isTranslationUnit()) {
58 Source<const DeclContext *> SourceParentDC =
59 LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
60 if (!SourceParentDC) {
61 // If we couldn't find the parent DC in this TranslationUnit, give up.
64 auto ND = cast<NamedDecl>(DC);
65 DeclarationName Name = ND->getDeclName();
66 Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
67 DeclContext::lookup_result SearchResult =
68 SourceParentDC.get()->lookup(SourceName.get());
69 size_t SearchResultSize = SearchResult.size();
70 // Handle multiple candidates once we have a test for it.
71 // This may turn up when we import template specializations correctly.
72 assert(SearchResultSize < 2);
73 if (SearchResultSize == 0) {
74 // couldn't find the name, so we have to give up
77 NamedDecl *SearchResultDecl = SearchResult[0];
78 return dyn_cast<DeclContext>(SearchResultDecl);
82 bool IsForwardDeclaration(Decl *D) {
83 assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
84 if (auto TD = dyn_cast<TagDecl>(D)) {
85 return !TD->isThisDeclarationADefinition();
86 } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
87 return !FD->isThisDeclarationADefinition();
93 template <typename CallbackType>
94 void ForEachMatchingDC(
95 const DeclContext *DC,
96 llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
97 CallbackType Callback) {
98 for (const ExternalASTMerger::ImporterPair &IP : Importers) {
99 Source<TranslationUnitDecl *> SourceTU =
100 IP.Forward->getFromContext().getTranslationUnitDecl();
101 if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
102 Callback(IP, SourceDC);
106 bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
107 return llvm::any_of(Decls, [&](const Candidate &D) {
108 return C.first.get()->getKind() == D.first.get()->getKind();
113 ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
114 llvm::ArrayRef<ImporterEndpoint> Sources) {
115 for (const ImporterEndpoint &S : Sources) {
117 {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
118 llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
119 /*MinimalImport=*/true)});
123 bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
124 DeclarationName Name) {
125 llvm::SmallVector<NamedDecl *, 1> Decls;
126 llvm::SmallVector<Candidate, 4> CompleteDecls;
127 llvm::SmallVector<Candidate, 4> ForwardDecls;
129 auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
130 if (IsForwardDeclaration(C.first.get())) {
131 if (!HasDeclOfSameType(ForwardDecls, C)) {
132 ForwardDecls.push_back(C);
135 CompleteDecls.push_back(C);
141 [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
142 DeclarationName FromName = IP.Reverse->Import(Name);
143 DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
144 for (NamedDecl *FromD : Result) {
145 FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
149 llvm::ArrayRef<Candidate> DeclsToReport =
150 CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
152 if (DeclsToReport.empty()) {
156 Decls.reserve(DeclsToReport.size());
157 for (const Candidate &C : DeclsToReport) {
158 NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
162 SetExternalVisibleDeclsForName(DC, Name, Decls);
166 void ExternalASTMerger::FindExternalLexicalDecls(
167 const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
168 SmallVectorImpl<Decl *> &Result) {
171 [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
172 for (const Decl *SourceDecl : SourceDC.get()->decls()) {
173 if (IsKindWeWant(SourceDecl->getKind())) {
175 IP.Forward->Import(const_cast<Decl *>(SourceDecl));
176 assert(ImportedDecl->getDeclContext() == DC);