xref: /freebsd/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric //  This file implements the ExternalASTMerger, which vends a combination of
10*0b57cec5SDimitry Andric //  ASTs from several different ASTContext/FileManager pairs
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
15*0b57cec5SDimitry Andric #include "clang/AST/Decl.h"
16*0b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
17*0b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
18*0b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
19*0b57cec5SDimitry Andric #include "clang/AST/ExternalASTMerger.h"
20*0b57cec5SDimitry Andric 
21*0b57cec5SDimitry Andric using namespace clang;
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric namespace {
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric template <typename T> struct Source {
26*0b57cec5SDimitry Andric   T t;
27*0b57cec5SDimitry Andric   Source(T t) : t(t) {}
28*0b57cec5SDimitry Andric   operator T() { return t; }
29*0b57cec5SDimitry Andric   template <typename U = T> U &get() { return t; }
30*0b57cec5SDimitry Andric   template <typename U = T> const U &get() const { return t; }
31*0b57cec5SDimitry Andric   template <typename U> operator Source<U>() { return Source<U>(t); }
32*0b57cec5SDimitry Andric };
33*0b57cec5SDimitry Andric 
34*0b57cec5SDimitry Andric typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric /// For the given DC, return the DC that is safe to perform lookups on.  This is
37*0b57cec5SDimitry Andric /// the DC we actually want to work with most of the time.
38*0b57cec5SDimitry Andric const DeclContext *CanonicalizeDC(const DeclContext *DC) {
39*0b57cec5SDimitry Andric   if (isa<LinkageSpecDecl>(DC))
40*0b57cec5SDimitry Andric     return DC->getRedeclContext();
41*0b57cec5SDimitry Andric   return DC;
42*0b57cec5SDimitry Andric }
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric Source<const DeclContext *>
45*0b57cec5SDimitry Andric LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
46*0b57cec5SDimitry Andric                   ASTImporter &ReverseImporter) {
47*0b57cec5SDimitry Andric   DC = CanonicalizeDC(DC);
48*0b57cec5SDimitry Andric   if (DC->isTranslationUnit()) {
49*0b57cec5SDimitry Andric     return SourceTU;
50*0b57cec5SDimitry Andric   }
51*0b57cec5SDimitry Andric   Source<const DeclContext *> SourceParentDC =
52*0b57cec5SDimitry Andric       LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
53*0b57cec5SDimitry Andric   if (!SourceParentDC) {
54*0b57cec5SDimitry Andric     // If we couldn't find the parent DC in this TranslationUnit, give up.
55*0b57cec5SDimitry Andric     return nullptr;
56*0b57cec5SDimitry Andric   }
57*0b57cec5SDimitry Andric   auto *ND = cast<NamedDecl>(DC);
58*0b57cec5SDimitry Andric   DeclarationName Name = ND->getDeclName();
59*0b57cec5SDimitry Andric   auto SourceNameOrErr = ReverseImporter.Import(Name);
60*0b57cec5SDimitry Andric   if (!SourceNameOrErr) {
61*0b57cec5SDimitry Andric     llvm::consumeError(SourceNameOrErr.takeError());
62*0b57cec5SDimitry Andric     return nullptr;
63*0b57cec5SDimitry Andric   }
64*0b57cec5SDimitry Andric   Source<DeclarationName> SourceName = *SourceNameOrErr;
65*0b57cec5SDimitry Andric   DeclContext::lookup_result SearchResult =
66*0b57cec5SDimitry Andric       SourceParentDC.get()->lookup(SourceName.get());
67*0b57cec5SDimitry Andric   size_t SearchResultSize = SearchResult.size();
68*0b57cec5SDimitry Andric   if (SearchResultSize == 0 || SearchResultSize > 1) {
69*0b57cec5SDimitry Andric     // There are two cases here.  First, we might not find the name.
70*0b57cec5SDimitry Andric     // We might also find multiple copies, in which case we have no
71*0b57cec5SDimitry Andric     // guarantee that the one we wanted is the one we pick.  (E.g.,
72*0b57cec5SDimitry Andric     // if we have two specializations of the same template it is
73*0b57cec5SDimitry Andric     // very hard to determine which is the one you want.)
74*0b57cec5SDimitry Andric     //
75*0b57cec5SDimitry Andric     // The Origins map fixes this problem by allowing the origin to be
76*0b57cec5SDimitry Andric     // explicitly recorded, so we trigger that recording by returning
77*0b57cec5SDimitry Andric     // nothing (rather than a possibly-inaccurate guess) here.
78*0b57cec5SDimitry Andric     return nullptr;
79*0b57cec5SDimitry Andric   } else {
80*0b57cec5SDimitry Andric     NamedDecl *SearchResultDecl = SearchResult[0];
81*0b57cec5SDimitry Andric     if (isa<DeclContext>(SearchResultDecl) &&
82*0b57cec5SDimitry Andric         SearchResultDecl->getKind() == DC->getDeclKind())
83*0b57cec5SDimitry Andric       return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
84*0b57cec5SDimitry Andric     return nullptr; // This type of lookup is unsupported
85*0b57cec5SDimitry Andric   }
86*0b57cec5SDimitry Andric }
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
89*0b57cec5SDimitry Andric ///
90*0b57cec5SDimitry Andric /// There are several modifications:
91*0b57cec5SDimitry Andric ///
92*0b57cec5SDimitry Andric /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
93*0b57cec5SDimitry Andric ///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
94*0b57cec5SDimitry Andric ///   forces MinimalImport to true, which is necessary to make this work.
95*0b57cec5SDimitry Andric /// - It maintains a reverse importer for use with names.  This allows lookup of
96*0b57cec5SDimitry Andric ///   arbitrary names in the source context.
97*0b57cec5SDimitry Andric /// - It updates the ExternalASTMerger's origin map as needed whenever a
98*0b57cec5SDimitry Andric ///   it sees a DeclContext.
99*0b57cec5SDimitry Andric class LazyASTImporter : public ASTImporter {
100*0b57cec5SDimitry Andric private:
101*0b57cec5SDimitry Andric   ExternalASTMerger &Parent;
102*0b57cec5SDimitry Andric   ASTImporter Reverse;
103*0b57cec5SDimitry Andric   const ExternalASTMerger::OriginMap &FromOrigins;
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric   llvm::raw_ostream &logs() { return Parent.logs(); }
106*0b57cec5SDimitry Andric public:
107*0b57cec5SDimitry Andric   LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
108*0b57cec5SDimitry Andric                   FileManager &ToFileManager, ASTContext &FromContext,
109*0b57cec5SDimitry Andric                   FileManager &FromFileManager,
110*0b57cec5SDimitry Andric                   const ExternalASTMerger::OriginMap &_FromOrigins)
111*0b57cec5SDimitry Andric       : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
112*0b57cec5SDimitry Andric                     /*MinimalImport=*/true),
113*0b57cec5SDimitry Andric         Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
114*0b57cec5SDimitry Andric                                  ToFileManager, /*MinimalImport=*/true), FromOrigins(_FromOrigins) {}
115*0b57cec5SDimitry Andric 
116*0b57cec5SDimitry Andric   /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
117*0b57cec5SDimitry Andric   /// map is kept up to date.  Also set the appropriate flags.
118*0b57cec5SDimitry Andric   void Imported(Decl *From, Decl *To) override {
119*0b57cec5SDimitry Andric     if (auto *ToDC = dyn_cast<DeclContext>(To)) {
120*0b57cec5SDimitry Andric       const bool LoggingEnabled = Parent.LoggingEnabled();
121*0b57cec5SDimitry Andric       if (LoggingEnabled)
122*0b57cec5SDimitry Andric         logs() << "(ExternalASTMerger*)" << (void*)&Parent
123*0b57cec5SDimitry Andric                << " imported (DeclContext*)" << (void*)ToDC
124*0b57cec5SDimitry Andric                << ", (ASTContext*)" << (void*)&getToContext()
125*0b57cec5SDimitry Andric                << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
126*0b57cec5SDimitry Andric                << ", (ASTContext*)" << (void*)&getFromContext()
127*0b57cec5SDimitry Andric                << "\n";
128*0b57cec5SDimitry Andric       Source<DeclContext *> FromDC(
129*0b57cec5SDimitry Andric           cast<DeclContext>(From)->getPrimaryContext());
130*0b57cec5SDimitry Andric       if (FromOrigins.count(FromDC) &&
131*0b57cec5SDimitry Andric           Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
132*0b57cec5SDimitry Andric         if (LoggingEnabled)
133*0b57cec5SDimitry Andric           logs() << "(ExternalASTMerger*)" << (void*)&Parent
134*0b57cec5SDimitry Andric                  << " forced origin (DeclContext*)"
135*0b57cec5SDimitry Andric                  << (void*)FromOrigins.at(FromDC).DC
136*0b57cec5SDimitry Andric                  << ", (ASTContext*)"
137*0b57cec5SDimitry Andric                  << (void*)FromOrigins.at(FromDC).AST
138*0b57cec5SDimitry Andric                  << "\n";
139*0b57cec5SDimitry Andric         Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
140*0b57cec5SDimitry Andric       } else {
141*0b57cec5SDimitry Andric         if (LoggingEnabled)
142*0b57cec5SDimitry Andric           logs() << "(ExternalASTMerger*)" << (void*)&Parent
143*0b57cec5SDimitry Andric                  << " maybe recording origin (DeclContext*)" << (void*)FromDC
144*0b57cec5SDimitry Andric                  << ", (ASTContext*)" << (void*)&getFromContext()
145*0b57cec5SDimitry Andric                  << "\n";
146*0b57cec5SDimitry Andric         Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
147*0b57cec5SDimitry Andric       }
148*0b57cec5SDimitry Andric     }
149*0b57cec5SDimitry Andric     if (auto *ToTag = dyn_cast<TagDecl>(To)) {
150*0b57cec5SDimitry Andric       ToTag->setHasExternalLexicalStorage();
151*0b57cec5SDimitry Andric       ToTag->getPrimaryContext()->setMustBuildLookupTable();
152*0b57cec5SDimitry Andric       assert(Parent.CanComplete(ToTag));
153*0b57cec5SDimitry Andric     } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
154*0b57cec5SDimitry Andric       ToNamespace->setHasExternalVisibleStorage();
155*0b57cec5SDimitry Andric       assert(Parent.CanComplete(ToNamespace));
156*0b57cec5SDimitry Andric     } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
157*0b57cec5SDimitry Andric       ToContainer->setHasExternalLexicalStorage();
158*0b57cec5SDimitry Andric       ToContainer->getPrimaryContext()->setMustBuildLookupTable();
159*0b57cec5SDimitry Andric       assert(Parent.CanComplete(ToContainer));
160*0b57cec5SDimitry Andric     }
161*0b57cec5SDimitry Andric   }
162*0b57cec5SDimitry Andric   ASTImporter &GetReverse() { return Reverse; }
163*0b57cec5SDimitry Andric };
164*0b57cec5SDimitry Andric 
165*0b57cec5SDimitry Andric bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
166*0b57cec5SDimitry Andric   if (isa<FunctionDecl>(C.first.get()))
167*0b57cec5SDimitry Andric     return false;
168*0b57cec5SDimitry Andric   return llvm::any_of(Decls, [&](const Candidate &D) {
169*0b57cec5SDimitry Andric     return C.first.get()->getKind() == D.first.get()->getKind();
170*0b57cec5SDimitry Andric   });
171*0b57cec5SDimitry Andric }
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric } // end namespace
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
176*0b57cec5SDimitry Andric   for (const std::unique_ptr<ASTImporter> &I : Importers)
177*0b57cec5SDimitry Andric     if (&I->getFromContext() == &OriginContext)
178*0b57cec5SDimitry Andric       return *I;
179*0b57cec5SDimitry Andric   llvm_unreachable("We should have an importer for this origin!");
180*0b57cec5SDimitry Andric }
181*0b57cec5SDimitry Andric 
182*0b57cec5SDimitry Andric namespace {
183*0b57cec5SDimitry Andric LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
184*0b57cec5SDimitry Andric                                    ASTContext &OriginContext) {
185*0b57cec5SDimitry Andric   return static_cast<LazyASTImporter &>(
186*0b57cec5SDimitry Andric       Merger.ImporterForOrigin(OriginContext));
187*0b57cec5SDimitry Andric }
188*0b57cec5SDimitry Andric }
189*0b57cec5SDimitry Andric 
190*0b57cec5SDimitry Andric bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
191*0b57cec5SDimitry Andric   for (const std::unique_ptr<ASTImporter> &I : Importers)
192*0b57cec5SDimitry Andric     if (&I->getFromContext() == &OriginContext)
193*0b57cec5SDimitry Andric       return true;
194*0b57cec5SDimitry Andric   return false;
195*0b57cec5SDimitry Andric }
196*0b57cec5SDimitry Andric 
197*0b57cec5SDimitry Andric template <typename CallbackType>
198*0b57cec5SDimitry Andric void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
199*0b57cec5SDimitry Andric                                           CallbackType Callback) {
200*0b57cec5SDimitry Andric   if (Origins.count(DC)) {
201*0b57cec5SDimitry Andric     ExternalASTMerger::DCOrigin Origin = Origins[DC];
202*0b57cec5SDimitry Andric     LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
203*0b57cec5SDimitry Andric     Callback(Importer, Importer.GetReverse(), Origin.DC);
204*0b57cec5SDimitry Andric   } else {
205*0b57cec5SDimitry Andric     bool DidCallback = false;
206*0b57cec5SDimitry Andric     for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
207*0b57cec5SDimitry Andric       Source<TranslationUnitDecl *> SourceTU =
208*0b57cec5SDimitry Andric           Importer->getFromContext().getTranslationUnitDecl();
209*0b57cec5SDimitry Andric       ASTImporter &Reverse =
210*0b57cec5SDimitry Andric           static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
211*0b57cec5SDimitry Andric       if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
212*0b57cec5SDimitry Andric         DidCallback = true;
213*0b57cec5SDimitry Andric         if (Callback(*Importer, Reverse, SourceDC))
214*0b57cec5SDimitry Andric           break;
215*0b57cec5SDimitry Andric       }
216*0b57cec5SDimitry Andric     }
217*0b57cec5SDimitry Andric     if (!DidCallback && LoggingEnabled())
218*0b57cec5SDimitry Andric       logs() << "(ExternalASTMerger*)" << (void*)this
219*0b57cec5SDimitry Andric              << " asserting for (DeclContext*)" << (const void*)DC
220*0b57cec5SDimitry Andric              << ", (ASTContext*)" << (void*)&Target.AST
221*0b57cec5SDimitry Andric              << "\n";
222*0b57cec5SDimitry Andric     assert(DidCallback && "Couldn't find a source context matching our DC");
223*0b57cec5SDimitry Andric   }
224*0b57cec5SDimitry Andric }
225*0b57cec5SDimitry Andric 
226*0b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(TagDecl *Tag) {
227*0b57cec5SDimitry Andric   assert(Tag->hasExternalLexicalStorage());
228*0b57cec5SDimitry Andric   ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
229*0b57cec5SDimitry Andric                              Source<const DeclContext *> SourceDC) -> bool {
230*0b57cec5SDimitry Andric     auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
231*0b57cec5SDimitry Andric     if (SourceTag->hasExternalLexicalStorage())
232*0b57cec5SDimitry Andric       SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
233*0b57cec5SDimitry Andric     if (!SourceTag->getDefinition())
234*0b57cec5SDimitry Andric       return false;
235*0b57cec5SDimitry Andric     Forward.MapImported(SourceTag, Tag);
236*0b57cec5SDimitry Andric     if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
237*0b57cec5SDimitry Andric       llvm::consumeError(std::move(Err));
238*0b57cec5SDimitry Andric     Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
239*0b57cec5SDimitry Andric     return true;
240*0b57cec5SDimitry Andric   });
241*0b57cec5SDimitry Andric }
242*0b57cec5SDimitry Andric 
243*0b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
244*0b57cec5SDimitry Andric   assert(Interface->hasExternalLexicalStorage());
245*0b57cec5SDimitry Andric   ForEachMatchingDC(
246*0b57cec5SDimitry Andric       Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
247*0b57cec5SDimitry Andric                      Source<const DeclContext *> SourceDC) -> bool {
248*0b57cec5SDimitry Andric         auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
249*0b57cec5SDimitry Andric             cast<ObjCInterfaceDecl>(SourceDC.get()));
250*0b57cec5SDimitry Andric         if (SourceInterface->hasExternalLexicalStorage())
251*0b57cec5SDimitry Andric           SourceInterface->getASTContext().getExternalSource()->CompleteType(
252*0b57cec5SDimitry Andric               SourceInterface);
253*0b57cec5SDimitry Andric         if (!SourceInterface->getDefinition())
254*0b57cec5SDimitry Andric           return false;
255*0b57cec5SDimitry Andric         Forward.MapImported(SourceInterface, Interface);
256*0b57cec5SDimitry Andric         if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
257*0b57cec5SDimitry Andric           llvm::consumeError(std::move(Err));
258*0b57cec5SDimitry Andric         return true;
259*0b57cec5SDimitry Andric       });
260*0b57cec5SDimitry Andric }
261*0b57cec5SDimitry Andric 
262*0b57cec5SDimitry Andric bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
263*0b57cec5SDimitry Andric   assert(Interface->hasExternalLexicalStorage() ||
264*0b57cec5SDimitry Andric          Interface->hasExternalVisibleStorage());
265*0b57cec5SDimitry Andric   bool FoundMatchingDC = false;
266*0b57cec5SDimitry Andric   ForEachMatchingDC(Interface,
267*0b57cec5SDimitry Andric                     [&](ASTImporter &Forward, ASTImporter &Reverse,
268*0b57cec5SDimitry Andric                         Source<const DeclContext *> SourceDC) -> bool {
269*0b57cec5SDimitry Andric                       FoundMatchingDC = true;
270*0b57cec5SDimitry Andric                       return true;
271*0b57cec5SDimitry Andric                     });
272*0b57cec5SDimitry Andric   return FoundMatchingDC;
273*0b57cec5SDimitry Andric }
274*0b57cec5SDimitry Andric 
275*0b57cec5SDimitry Andric namespace {
276*0b57cec5SDimitry Andric bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
277*0b57cec5SDimitry Andric   if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
278*0b57cec5SDimitry Andric     return true; // There are many cases where Objective-C is ambiguous.
279*0b57cec5SDimitry Andric   if (auto *T1 = dyn_cast<TagDecl>(D1))
280*0b57cec5SDimitry Andric     if (auto *T2 = dyn_cast<TagDecl>(D2))
281*0b57cec5SDimitry Andric       if (T1->getFirstDecl() == T2->getFirstDecl())
282*0b57cec5SDimitry Andric         return true;
283*0b57cec5SDimitry Andric   return D1 == D2 || D1 == CanonicalizeDC(D2);
284*0b57cec5SDimitry Andric }
285*0b57cec5SDimitry Andric }
286*0b57cec5SDimitry Andric 
287*0b57cec5SDimitry Andric void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
288*0b57cec5SDimitry Andric                                           DCOrigin Origin) {
289*0b57cec5SDimitry Andric   LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
290*0b57cec5SDimitry Andric   ASTImporter &Reverse = Importer.GetReverse();
291*0b57cec5SDimitry Andric   Source<const DeclContext *> FoundFromDC =
292*0b57cec5SDimitry Andric       LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
293*0b57cec5SDimitry Andric   const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
294*0b57cec5SDimitry Andric   if (DoRecord)
295*0b57cec5SDimitry Andric     RecordOriginImpl(ToDC, Origin, Importer);
296*0b57cec5SDimitry Andric   if (LoggingEnabled())
297*0b57cec5SDimitry Andric     logs() << "(ExternalASTMerger*)" << (void*)this
298*0b57cec5SDimitry Andric              << (DoRecord ? " decided " : " decided NOT")
299*0b57cec5SDimitry Andric              << " to record origin (DeclContext*)" << (void*)Origin.DC
300*0b57cec5SDimitry Andric              << ", (ASTContext*)" << (void*)&Origin.AST
301*0b57cec5SDimitry Andric              << "\n";
302*0b57cec5SDimitry Andric }
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
305*0b57cec5SDimitry Andric                                           DCOrigin Origin) {
306*0b57cec5SDimitry Andric   RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
307*0b57cec5SDimitry Andric }
308*0b57cec5SDimitry Andric 
309*0b57cec5SDimitry Andric void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
310*0b57cec5SDimitry Andric                                          ASTImporter &Importer) {
311*0b57cec5SDimitry Andric   Origins[ToDC] = Origin;
312*0b57cec5SDimitry Andric   Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
313*0b57cec5SDimitry Andric }
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
316*0b57cec5SDimitry Andric                                      llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
317*0b57cec5SDimitry Andric   AddSources(Sources);
318*0b57cec5SDimitry Andric }
319*0b57cec5SDimitry Andric 
320*0b57cec5SDimitry Andric void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
321*0b57cec5SDimitry Andric   for (const ImporterSource &S : Sources) {
322*0b57cec5SDimitry Andric     assert(&S.AST != &Target.AST);
323*0b57cec5SDimitry Andric     Importers.push_back(llvm::make_unique<LazyASTImporter>(
324*0b57cec5SDimitry Andric         *this, Target.AST, Target.FM, S.AST, S.FM, S.OM));
325*0b57cec5SDimitry Andric   }
326*0b57cec5SDimitry Andric }
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
329*0b57cec5SDimitry Andric   if (LoggingEnabled())
330*0b57cec5SDimitry Andric     for (const ImporterSource &S : Sources)
331*0b57cec5SDimitry Andric       logs() << "(ExternalASTMerger*)" << (void*)this
332*0b57cec5SDimitry Andric              << " removing source (ASTContext*)" << (void*)&S.AST
333*0b57cec5SDimitry Andric              << "\n";
334*0b57cec5SDimitry Andric   Importers.erase(
335*0b57cec5SDimitry Andric       std::remove_if(Importers.begin(), Importers.end(),
336*0b57cec5SDimitry Andric                      [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
337*0b57cec5SDimitry Andric                        for (const ImporterSource &S : Sources) {
338*0b57cec5SDimitry Andric                          if (&Importer->getFromContext() == &S.AST)
339*0b57cec5SDimitry Andric                            return true;
340*0b57cec5SDimitry Andric                        }
341*0b57cec5SDimitry Andric                        return false;
342*0b57cec5SDimitry Andric                      }),
343*0b57cec5SDimitry Andric       Importers.end());
344*0b57cec5SDimitry Andric   for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
345*0b57cec5SDimitry Andric     std::pair<const DeclContext *, DCOrigin> Origin = *OI;
346*0b57cec5SDimitry Andric     bool Erase = false;
347*0b57cec5SDimitry Andric     for (const ImporterSource &S : Sources) {
348*0b57cec5SDimitry Andric       if (&S.AST == Origin.second.AST) {
349*0b57cec5SDimitry Andric         Erase = true;
350*0b57cec5SDimitry Andric         break;
351*0b57cec5SDimitry Andric       }
352*0b57cec5SDimitry Andric     }
353*0b57cec5SDimitry Andric     if (Erase)
354*0b57cec5SDimitry Andric       OI = Origins.erase(OI);
355*0b57cec5SDimitry Andric     else
356*0b57cec5SDimitry Andric       ++OI;
357*0b57cec5SDimitry Andric   }
358*0b57cec5SDimitry Andric }
359*0b57cec5SDimitry Andric 
360*0b57cec5SDimitry Andric template <typename DeclTy>
361*0b57cec5SDimitry Andric static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
362*0b57cec5SDimitry Andric   for (auto *Spec : D->specializations()) {
363*0b57cec5SDimitry Andric     auto ImportedSpecOrError = Importer->Import(Spec);
364*0b57cec5SDimitry Andric     if (!ImportedSpecOrError) {
365*0b57cec5SDimitry Andric       llvm::consumeError(ImportedSpecOrError.takeError());
366*0b57cec5SDimitry Andric       return true;
367*0b57cec5SDimitry Andric     }
368*0b57cec5SDimitry Andric   }
369*0b57cec5SDimitry Andric   return false;
370*0b57cec5SDimitry Andric }
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric /// Imports specializations from template declarations that can be specialized.
373*0b57cec5SDimitry Andric static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
374*0b57cec5SDimitry Andric   if (!isa<TemplateDecl>(D))
375*0b57cec5SDimitry Andric     return false;
376*0b57cec5SDimitry Andric   if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
377*0b57cec5SDimitry Andric     return importSpecializations(FunctionTD, Importer);
378*0b57cec5SDimitry Andric   else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
379*0b57cec5SDimitry Andric     return importSpecializations(ClassTD, Importer);
380*0b57cec5SDimitry Andric   else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
381*0b57cec5SDimitry Andric     return importSpecializations(VarTD, Importer);
382*0b57cec5SDimitry Andric   return false;
383*0b57cec5SDimitry Andric }
384*0b57cec5SDimitry Andric 
385*0b57cec5SDimitry Andric bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
386*0b57cec5SDimitry Andric                                                        DeclarationName Name) {
387*0b57cec5SDimitry Andric   llvm::SmallVector<NamedDecl *, 1> Decls;
388*0b57cec5SDimitry Andric   llvm::SmallVector<Candidate, 4> Candidates;
389*0b57cec5SDimitry Andric 
390*0b57cec5SDimitry Andric   auto FilterFoundDecl = [&Candidates](const Candidate &C) {
391*0b57cec5SDimitry Andric    if (!HasDeclOfSameType(Candidates, C))
392*0b57cec5SDimitry Andric      Candidates.push_back(C);
393*0b57cec5SDimitry Andric   };
394*0b57cec5SDimitry Andric 
395*0b57cec5SDimitry Andric   ForEachMatchingDC(DC,
396*0b57cec5SDimitry Andric                     [&](ASTImporter &Forward, ASTImporter &Reverse,
397*0b57cec5SDimitry Andric                         Source<const DeclContext *> SourceDC) -> bool {
398*0b57cec5SDimitry Andric                       auto FromNameOrErr = Reverse.Import(Name);
399*0b57cec5SDimitry Andric                       if (!FromNameOrErr) {
400*0b57cec5SDimitry Andric                         llvm::consumeError(FromNameOrErr.takeError());
401*0b57cec5SDimitry Andric                         return false;
402*0b57cec5SDimitry Andric                       }
403*0b57cec5SDimitry Andric                       DeclContextLookupResult Result =
404*0b57cec5SDimitry Andric                           SourceDC.get()->lookup(*FromNameOrErr);
405*0b57cec5SDimitry Andric                       for (NamedDecl *FromD : Result) {
406*0b57cec5SDimitry Andric                         FilterFoundDecl(std::make_pair(FromD, &Forward));
407*0b57cec5SDimitry Andric                       }
408*0b57cec5SDimitry Andric                       return false;
409*0b57cec5SDimitry Andric                     });
410*0b57cec5SDimitry Andric 
411*0b57cec5SDimitry Andric   if (Candidates.empty())
412*0b57cec5SDimitry Andric     return false;
413*0b57cec5SDimitry Andric 
414*0b57cec5SDimitry Andric   Decls.reserve(Candidates.size());
415*0b57cec5SDimitry Andric   for (const Candidate &C : Candidates) {
416*0b57cec5SDimitry Andric     Decl *LookupRes = C.first.get();
417*0b57cec5SDimitry Andric     ASTImporter *Importer = C.second;
418*0b57cec5SDimitry Andric     auto NDOrErr = Importer->Import(LookupRes);
419*0b57cec5SDimitry Andric     assert(NDOrErr);
420*0b57cec5SDimitry Andric     (void)static_cast<bool>(NDOrErr);
421*0b57cec5SDimitry Andric     NamedDecl *ND = cast_or_null<NamedDecl>(*NDOrErr);
422*0b57cec5SDimitry Andric     assert(ND);
423*0b57cec5SDimitry Andric     // If we don't import specialization, they are not available via lookup
424*0b57cec5SDimitry Andric     // because the lookup result is imported TemplateDecl and it does not
425*0b57cec5SDimitry Andric     // reference its specializations until they are imported explicitly.
426*0b57cec5SDimitry Andric     bool IsSpecImportFailed =
427*0b57cec5SDimitry Andric         importSpecializationsIfNeeded(LookupRes, Importer);
428*0b57cec5SDimitry Andric     assert(!IsSpecImportFailed);
429*0b57cec5SDimitry Andric     (void)IsSpecImportFailed;
430*0b57cec5SDimitry Andric     Decls.push_back(ND);
431*0b57cec5SDimitry Andric   }
432*0b57cec5SDimitry Andric   SetExternalVisibleDeclsForName(DC, Name, Decls);
433*0b57cec5SDimitry Andric   return true;
434*0b57cec5SDimitry Andric }
435*0b57cec5SDimitry Andric 
436*0b57cec5SDimitry Andric void ExternalASTMerger::FindExternalLexicalDecls(
437*0b57cec5SDimitry Andric     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
438*0b57cec5SDimitry Andric     SmallVectorImpl<Decl *> &Result) {
439*0b57cec5SDimitry Andric   ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
440*0b57cec5SDimitry Andric                             Source<const DeclContext *> SourceDC) -> bool {
441*0b57cec5SDimitry Andric     for (const Decl *SourceDecl : SourceDC.get()->decls()) {
442*0b57cec5SDimitry Andric       if (IsKindWeWant(SourceDecl->getKind())) {
443*0b57cec5SDimitry Andric         auto ImportedDeclOrErr = Forward.Import(SourceDecl);
444*0b57cec5SDimitry Andric         if (ImportedDeclOrErr)
445*0b57cec5SDimitry Andric           assert(!(*ImportedDeclOrErr) ||
446*0b57cec5SDimitry Andric                  IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
447*0b57cec5SDimitry Andric         else
448*0b57cec5SDimitry Andric           llvm::consumeError(ImportedDeclOrErr.takeError());
449*0b57cec5SDimitry Andric       }
450*0b57cec5SDimitry Andric     }
451*0b57cec5SDimitry Andric     return false;
452*0b57cec5SDimitry Andric   });
453*0b57cec5SDimitry Andric }
454*0b57cec5SDimitry Andric 
455