xref: /openbsd-src/gnu/llvm/clang/lib/AST/ExternalASTMerger.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file implements the ExternalASTMerger, which vends a combination of
10e5dd7070Spatrick //  ASTs from several different ASTContext/FileManager pairs
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/AST/ASTContext.h"
15e5dd7070Spatrick #include "clang/AST/Decl.h"
16e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
17e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
18e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
19e5dd7070Spatrick #include "clang/AST/ExternalASTMerger.h"
20e5dd7070Spatrick 
21e5dd7070Spatrick using namespace clang;
22e5dd7070Spatrick 
23e5dd7070Spatrick namespace {
24e5dd7070Spatrick 
25e5dd7070Spatrick template <typename T> struct Source {
26e5dd7070Spatrick   T t;
Source__anon24c518b50111::Source27e5dd7070Spatrick   Source(T t) : t(t) {}
operator T__anon24c518b50111::Source28e5dd7070Spatrick   operator T() { return t; }
get__anon24c518b50111::Source29e5dd7070Spatrick   template <typename U = T> U &get() { return t; }
get__anon24c518b50111::Source30e5dd7070Spatrick   template <typename U = T> const U &get() const { return t; }
operator Source<U>__anon24c518b50111::Source31e5dd7070Spatrick   template <typename U> operator Source<U>() { return Source<U>(t); }
32e5dd7070Spatrick };
33e5dd7070Spatrick 
34e5dd7070Spatrick typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
35e5dd7070Spatrick 
36e5dd7070Spatrick /// For the given DC, return the DC that is safe to perform lookups on.  This is
37e5dd7070Spatrick /// the DC we actually want to work with most of the time.
CanonicalizeDC(const DeclContext * DC)38e5dd7070Spatrick const DeclContext *CanonicalizeDC(const DeclContext *DC) {
39e5dd7070Spatrick   if (isa<LinkageSpecDecl>(DC))
40e5dd7070Spatrick     return DC->getRedeclContext();
41e5dd7070Spatrick   return DC;
42e5dd7070Spatrick }
43e5dd7070Spatrick 
44e5dd7070Spatrick Source<const DeclContext *>
LookupSameContext(Source<TranslationUnitDecl * > SourceTU,const DeclContext * DC,ASTImporter & ReverseImporter)45e5dd7070Spatrick LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
46e5dd7070Spatrick                   ASTImporter &ReverseImporter) {
47e5dd7070Spatrick   DC = CanonicalizeDC(DC);
48e5dd7070Spatrick   if (DC->isTranslationUnit()) {
49e5dd7070Spatrick     return SourceTU;
50e5dd7070Spatrick   }
51e5dd7070Spatrick   Source<const DeclContext *> SourceParentDC =
52e5dd7070Spatrick       LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
53e5dd7070Spatrick   if (!SourceParentDC) {
54e5dd7070Spatrick     // If we couldn't find the parent DC in this TranslationUnit, give up.
55e5dd7070Spatrick     return nullptr;
56e5dd7070Spatrick   }
57e5dd7070Spatrick   auto *ND = cast<NamedDecl>(DC);
58e5dd7070Spatrick   DeclarationName Name = ND->getDeclName();
59e5dd7070Spatrick   auto SourceNameOrErr = ReverseImporter.Import(Name);
60e5dd7070Spatrick   if (!SourceNameOrErr) {
61e5dd7070Spatrick     llvm::consumeError(SourceNameOrErr.takeError());
62e5dd7070Spatrick     return nullptr;
63e5dd7070Spatrick   }
64e5dd7070Spatrick   Source<DeclarationName> SourceName = *SourceNameOrErr;
65e5dd7070Spatrick   DeclContext::lookup_result SearchResult =
66e5dd7070Spatrick       SourceParentDC.get()->lookup(SourceName.get());
67a9ac8606Spatrick 
68e5dd7070Spatrick   // There are two cases here. First, we might not find the name.
69e5dd7070Spatrick   // We might also find multiple copies, in which case we have no
70e5dd7070Spatrick   // guarantee that the one we wanted is the one we pick.  (E.g.,
71e5dd7070Spatrick   // if we have two specializations of the same template it is
72e5dd7070Spatrick   // very hard to determine which is the one you want.)
73e5dd7070Spatrick   //
74e5dd7070Spatrick   // The Origins map fixes this problem by allowing the origin to be
75e5dd7070Spatrick   // explicitly recorded, so we trigger that recording by returning
76e5dd7070Spatrick   // nothing (rather than a possibly-inaccurate guess) here.
77a9ac8606Spatrick   if (SearchResult.isSingleResult()) {
78a9ac8606Spatrick     NamedDecl *SearchResultDecl = SearchResult.front();
79e5dd7070Spatrick     if (isa<DeclContext>(SearchResultDecl) &&
80e5dd7070Spatrick         SearchResultDecl->getKind() == DC->getDeclKind())
81e5dd7070Spatrick       return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
82e5dd7070Spatrick     return nullptr; // This type of lookup is unsupported
83a9ac8606Spatrick   } else {
84a9ac8606Spatrick     return nullptr;
85e5dd7070Spatrick   }
86e5dd7070Spatrick }
87e5dd7070Spatrick 
88e5dd7070Spatrick /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
89e5dd7070Spatrick ///
90e5dd7070Spatrick /// There are several modifications:
91e5dd7070Spatrick ///
92e5dd7070Spatrick /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
93e5dd7070Spatrick ///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
94e5dd7070Spatrick ///   forces MinimalImport to true, which is necessary to make this work.
95e5dd7070Spatrick /// - It maintains a reverse importer for use with names.  This allows lookup of
96e5dd7070Spatrick ///   arbitrary names in the source context.
97e5dd7070Spatrick /// - It updates the ExternalASTMerger's origin map as needed whenever a
98e5dd7070Spatrick ///   it sees a DeclContext.
99e5dd7070Spatrick class LazyASTImporter : public ASTImporter {
100e5dd7070Spatrick private:
101e5dd7070Spatrick   ExternalASTMerger &Parent;
102e5dd7070Spatrick   ASTImporter Reverse;
103e5dd7070Spatrick   const ExternalASTMerger::OriginMap &FromOrigins;
104e5dd7070Spatrick   /// @see ExternalASTMerger::ImporterSource::Temporary
105e5dd7070Spatrick   bool TemporarySource;
106e5dd7070Spatrick   /// Map of imported declarations back to the declarations they originated
107e5dd7070Spatrick   /// from.
108e5dd7070Spatrick   llvm::DenseMap<Decl *, Decl *> ToOrigin;
109e5dd7070Spatrick   /// @see ExternalASTMerger::ImporterSource::Merger
110e5dd7070Spatrick   ExternalASTMerger *SourceMerger;
logs()111e5dd7070Spatrick   llvm::raw_ostream &logs() { return Parent.logs(); }
112e5dd7070Spatrick public:
LazyASTImporter(ExternalASTMerger & _Parent,ASTContext & ToContext,FileManager & ToFileManager,const ExternalASTMerger::ImporterSource & S,std::shared_ptr<ASTImporterSharedState> SharedState)113e5dd7070Spatrick   LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
114e5dd7070Spatrick                   FileManager &ToFileManager,
115e5dd7070Spatrick                   const ExternalASTMerger::ImporterSource &S,
116e5dd7070Spatrick                   std::shared_ptr<ASTImporterSharedState> SharedState)
117e5dd7070Spatrick       : ASTImporter(ToContext, ToFileManager, S.getASTContext(),
118e5dd7070Spatrick                     S.getFileManager(),
119e5dd7070Spatrick                     /*MinimalImport=*/true, SharedState),
120e5dd7070Spatrick         Parent(_Parent),
121e5dd7070Spatrick         Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager,
122e5dd7070Spatrick                 /*MinimalImport=*/true),
123e5dd7070Spatrick         FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()),
124e5dd7070Spatrick         SourceMerger(S.getMerger()) {}
125e5dd7070Spatrick 
ImportImpl(Decl * FromD)126e5dd7070Spatrick   llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
127e5dd7070Spatrick     if (!TemporarySource || !SourceMerger)
128e5dd7070Spatrick       return ASTImporter::ImportImpl(FromD);
129e5dd7070Spatrick 
130e5dd7070Spatrick     // If we get here, then this source is importing from a temporary ASTContext
131e5dd7070Spatrick     // that also has another ExternalASTMerger attached. It could be
132e5dd7070Spatrick     // possible that the current ExternalASTMerger and the temporary ASTContext
133e5dd7070Spatrick     // share a common ImporterSource, which means that the temporary
134e5dd7070Spatrick     // AST could contain declarations that were imported from a source
135e5dd7070Spatrick     // that this ExternalASTMerger can access directly. Instead of importing
136e5dd7070Spatrick     // such declarations from the temporary ASTContext, they should instead
137e5dd7070Spatrick     // be directly imported by this ExternalASTMerger from the original
138e5dd7070Spatrick     // source. This way the ExternalASTMerger can safely do a minimal import
139e5dd7070Spatrick     // without creating incomplete declarations originated from a temporary
140e5dd7070Spatrick     // ASTContext. If we would try to complete such declarations later on, we
141e5dd7070Spatrick     // would fail to do so as their temporary AST could be deleted (which means
142e5dd7070Spatrick     // that the missing parts of the minimally imported declaration in that
143e5dd7070Spatrick     // ASTContext were also deleted).
144e5dd7070Spatrick     //
145e5dd7070Spatrick     // The following code tracks back any declaration that needs to be
146e5dd7070Spatrick     // imported from the temporary ASTContext to a persistent ASTContext.
147e5dd7070Spatrick     // Then the ExternalASTMerger tries to import from the persistent
148e5dd7070Spatrick     // ASTContext directly by using the associated ASTImporter. If that
149e5dd7070Spatrick     // succeeds, this ASTImporter just maps the declarations imported by
150e5dd7070Spatrick     // the other (persistent) ASTImporter to this (temporary) ASTImporter.
151e5dd7070Spatrick     // The steps can be visualized like this:
152e5dd7070Spatrick     //
153e5dd7070Spatrick     //  Target AST <--- 3. Indirect import --- Persistent AST
154e5dd7070Spatrick     //       ^            of persistent decl        ^
155e5dd7070Spatrick     //       |                                      |
156e5dd7070Spatrick     // 1. Current import           2. Tracking back to persistent decl
157e5dd7070Spatrick     // 4. Map persistent decl                       |
158e5dd7070Spatrick     //  & pretend we imported.                      |
159e5dd7070Spatrick     //       |                                      |
160e5dd7070Spatrick     // Temporary AST -------------------------------'
161e5dd7070Spatrick 
162e5dd7070Spatrick     // First, ask the ExternalASTMerger of the source where the temporary
163e5dd7070Spatrick     // declaration originated from.
164e5dd7070Spatrick     Decl *Persistent = SourceMerger->FindOriginalDecl(FromD);
165e5dd7070Spatrick     // FromD isn't from a persistent AST, so just do a normal import.
166e5dd7070Spatrick     if (!Persistent)
167e5dd7070Spatrick       return ASTImporter::ImportImpl(FromD);
168e5dd7070Spatrick     // Now ask the current ExternalASTMerger to try import the persistent
169e5dd7070Spatrick     // declaration into the target.
170e5dd7070Spatrick     ASTContext &PersistentCtx = Persistent->getASTContext();
171e5dd7070Spatrick     ASTImporter &OtherImporter = Parent.ImporterForOrigin(PersistentCtx);
172e5dd7070Spatrick     // Check that we never end up in the current Importer again.
173e5dd7070Spatrick     assert((&PersistentCtx != &getFromContext()) && (&OtherImporter != this) &&
174e5dd7070Spatrick            "Delegated to same Importer?");
175e5dd7070Spatrick     auto DeclOrErr = OtherImporter.Import(Persistent);
176e5dd7070Spatrick     // Errors when importing the persistent decl are treated as if we
177e5dd7070Spatrick     // had errors with importing the temporary decl.
178e5dd7070Spatrick     if (!DeclOrErr)
179e5dd7070Spatrick       return DeclOrErr.takeError();
180e5dd7070Spatrick     Decl *D = *DeclOrErr;
181e5dd7070Spatrick     // Tell the current ASTImporter that this has already been imported
182e5dd7070Spatrick     // to prevent any further queries for the temporary decl.
183e5dd7070Spatrick     MapImported(FromD, D);
184e5dd7070Spatrick     return D;
185e5dd7070Spatrick   }
186e5dd7070Spatrick 
187e5dd7070Spatrick   /// Implements the ASTImporter interface for tracking back a declaration
188e5dd7070Spatrick   /// to its original declaration it came from.
GetOriginalDecl(Decl * To)189e5dd7070Spatrick   Decl *GetOriginalDecl(Decl *To) override {
190e5dd7070Spatrick     auto It = ToOrigin.find(To);
191e5dd7070Spatrick     if (It != ToOrigin.end())
192e5dd7070Spatrick       return It->second;
193e5dd7070Spatrick     return nullptr;
194e5dd7070Spatrick   }
195e5dd7070Spatrick 
196e5dd7070Spatrick   /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
197e5dd7070Spatrick   /// map is kept up to date.  Also set the appropriate flags.
Imported(Decl * From,Decl * To)198e5dd7070Spatrick   void Imported(Decl *From, Decl *To) override {
199e5dd7070Spatrick     ToOrigin[To] = From;
200e5dd7070Spatrick 
201e5dd7070Spatrick     if (auto *ToDC = dyn_cast<DeclContext>(To)) {
202e5dd7070Spatrick       const bool LoggingEnabled = Parent.LoggingEnabled();
203e5dd7070Spatrick       if (LoggingEnabled)
204e5dd7070Spatrick         logs() << "(ExternalASTMerger*)" << (void*)&Parent
205e5dd7070Spatrick                << " imported (DeclContext*)" << (void*)ToDC
206e5dd7070Spatrick                << ", (ASTContext*)" << (void*)&getToContext()
207e5dd7070Spatrick                << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
208e5dd7070Spatrick                << ", (ASTContext*)" << (void*)&getFromContext()
209e5dd7070Spatrick                << "\n";
210e5dd7070Spatrick       Source<DeclContext *> FromDC(
211e5dd7070Spatrick           cast<DeclContext>(From)->getPrimaryContext());
212e5dd7070Spatrick       if (FromOrigins.count(FromDC) &&
213e5dd7070Spatrick           Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
214e5dd7070Spatrick         if (LoggingEnabled)
215e5dd7070Spatrick           logs() << "(ExternalASTMerger*)" << (void*)&Parent
216e5dd7070Spatrick                  << " forced origin (DeclContext*)"
217e5dd7070Spatrick                  << (void*)FromOrigins.at(FromDC).DC
218e5dd7070Spatrick                  << ", (ASTContext*)"
219e5dd7070Spatrick                  << (void*)FromOrigins.at(FromDC).AST
220e5dd7070Spatrick                  << "\n";
221e5dd7070Spatrick         Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
222e5dd7070Spatrick       } else {
223e5dd7070Spatrick         if (LoggingEnabled)
224e5dd7070Spatrick           logs() << "(ExternalASTMerger*)" << (void*)&Parent
225e5dd7070Spatrick                  << " maybe recording origin (DeclContext*)" << (void*)FromDC
226e5dd7070Spatrick                  << ", (ASTContext*)" << (void*)&getFromContext()
227e5dd7070Spatrick                  << "\n";
228e5dd7070Spatrick         Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
229e5dd7070Spatrick       }
230e5dd7070Spatrick     }
231e5dd7070Spatrick     if (auto *ToTag = dyn_cast<TagDecl>(To)) {
232e5dd7070Spatrick       ToTag->setHasExternalLexicalStorage();
233e5dd7070Spatrick       ToTag->getPrimaryContext()->setMustBuildLookupTable();
234e5dd7070Spatrick       assert(Parent.CanComplete(ToTag));
235e5dd7070Spatrick     } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
236e5dd7070Spatrick       ToNamespace->setHasExternalVisibleStorage();
237e5dd7070Spatrick       assert(Parent.CanComplete(ToNamespace));
238e5dd7070Spatrick     } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
239e5dd7070Spatrick       ToContainer->setHasExternalLexicalStorage();
240e5dd7070Spatrick       ToContainer->getPrimaryContext()->setMustBuildLookupTable();
241e5dd7070Spatrick       assert(Parent.CanComplete(ToContainer));
242e5dd7070Spatrick     }
243e5dd7070Spatrick   }
GetReverse()244e5dd7070Spatrick   ASTImporter &GetReverse() { return Reverse; }
245e5dd7070Spatrick };
246e5dd7070Spatrick 
HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls,const Candidate & C)247e5dd7070Spatrick bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
248e5dd7070Spatrick   if (isa<FunctionDecl>(C.first.get()))
249e5dd7070Spatrick     return false;
250e5dd7070Spatrick   return llvm::any_of(Decls, [&](const Candidate &D) {
251e5dd7070Spatrick     return C.first.get()->getKind() == D.first.get()->getKind();
252e5dd7070Spatrick   });
253e5dd7070Spatrick }
254e5dd7070Spatrick 
255e5dd7070Spatrick } // end namespace
256e5dd7070Spatrick 
ImporterForOrigin(ASTContext & OriginContext)257e5dd7070Spatrick ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
258e5dd7070Spatrick   for (const std::unique_ptr<ASTImporter> &I : Importers)
259e5dd7070Spatrick     if (&I->getFromContext() == &OriginContext)
260e5dd7070Spatrick       return *I;
261e5dd7070Spatrick   llvm_unreachable("We should have an importer for this origin!");
262e5dd7070Spatrick }
263e5dd7070Spatrick 
264e5dd7070Spatrick namespace {
LazyImporterForOrigin(ExternalASTMerger & Merger,ASTContext & OriginContext)265e5dd7070Spatrick LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
266e5dd7070Spatrick                                    ASTContext &OriginContext) {
267e5dd7070Spatrick   return static_cast<LazyASTImporter &>(
268e5dd7070Spatrick       Merger.ImporterForOrigin(OriginContext));
269e5dd7070Spatrick }
270e5dd7070Spatrick }
271e5dd7070Spatrick 
HasImporterForOrigin(ASTContext & OriginContext)272e5dd7070Spatrick bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
273e5dd7070Spatrick   for (const std::unique_ptr<ASTImporter> &I : Importers)
274e5dd7070Spatrick     if (&I->getFromContext() == &OriginContext)
275e5dd7070Spatrick       return true;
276e5dd7070Spatrick   return false;
277e5dd7070Spatrick }
278e5dd7070Spatrick 
279e5dd7070Spatrick template <typename CallbackType>
ForEachMatchingDC(const DeclContext * DC,CallbackType Callback)280e5dd7070Spatrick void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
281e5dd7070Spatrick                                           CallbackType Callback) {
282e5dd7070Spatrick   if (Origins.count(DC)) {
283e5dd7070Spatrick     ExternalASTMerger::DCOrigin Origin = Origins[DC];
284e5dd7070Spatrick     LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285e5dd7070Spatrick     Callback(Importer, Importer.GetReverse(), Origin.DC);
286e5dd7070Spatrick   } else {
287e5dd7070Spatrick     bool DidCallback = false;
288e5dd7070Spatrick     for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289e5dd7070Spatrick       Source<TranslationUnitDecl *> SourceTU =
290e5dd7070Spatrick           Importer->getFromContext().getTranslationUnitDecl();
291e5dd7070Spatrick       ASTImporter &Reverse =
292e5dd7070Spatrick           static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293e5dd7070Spatrick       if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294e5dd7070Spatrick         DidCallback = true;
295e5dd7070Spatrick         if (Callback(*Importer, Reverse, SourceDC))
296e5dd7070Spatrick           break;
297e5dd7070Spatrick       }
298e5dd7070Spatrick     }
299e5dd7070Spatrick     if (!DidCallback && LoggingEnabled())
300e5dd7070Spatrick       logs() << "(ExternalASTMerger*)" << (void*)this
301e5dd7070Spatrick              << " asserting for (DeclContext*)" << (const void*)DC
302e5dd7070Spatrick              << ", (ASTContext*)" << (void*)&Target.AST
303e5dd7070Spatrick              << "\n";
304e5dd7070Spatrick     assert(DidCallback && "Couldn't find a source context matching our DC");
305e5dd7070Spatrick   }
306e5dd7070Spatrick }
307e5dd7070Spatrick 
CompleteType(TagDecl * Tag)308e5dd7070Spatrick void ExternalASTMerger::CompleteType(TagDecl *Tag) {
309e5dd7070Spatrick   assert(Tag->hasExternalLexicalStorage());
310e5dd7070Spatrick   ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
311e5dd7070Spatrick                              Source<const DeclContext *> SourceDC) -> bool {
312e5dd7070Spatrick     auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
313e5dd7070Spatrick     if (SourceTag->hasExternalLexicalStorage())
314e5dd7070Spatrick       SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
315e5dd7070Spatrick     if (!SourceTag->getDefinition())
316e5dd7070Spatrick       return false;
317e5dd7070Spatrick     Forward.MapImported(SourceTag, Tag);
318e5dd7070Spatrick     if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
319e5dd7070Spatrick       llvm::consumeError(std::move(Err));
320e5dd7070Spatrick     Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
321e5dd7070Spatrick     return true;
322e5dd7070Spatrick   });
323e5dd7070Spatrick }
324e5dd7070Spatrick 
CompleteType(ObjCInterfaceDecl * Interface)325e5dd7070Spatrick void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
326e5dd7070Spatrick   assert(Interface->hasExternalLexicalStorage());
327e5dd7070Spatrick   ForEachMatchingDC(
328e5dd7070Spatrick       Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
329e5dd7070Spatrick                      Source<const DeclContext *> SourceDC) -> bool {
330e5dd7070Spatrick         auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
331e5dd7070Spatrick             cast<ObjCInterfaceDecl>(SourceDC.get()));
332e5dd7070Spatrick         if (SourceInterface->hasExternalLexicalStorage())
333e5dd7070Spatrick           SourceInterface->getASTContext().getExternalSource()->CompleteType(
334e5dd7070Spatrick               SourceInterface);
335e5dd7070Spatrick         if (!SourceInterface->getDefinition())
336e5dd7070Spatrick           return false;
337e5dd7070Spatrick         Forward.MapImported(SourceInterface, Interface);
338e5dd7070Spatrick         if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
339e5dd7070Spatrick           llvm::consumeError(std::move(Err));
340e5dd7070Spatrick         return true;
341e5dd7070Spatrick       });
342e5dd7070Spatrick }
343e5dd7070Spatrick 
CanComplete(DeclContext * Interface)344e5dd7070Spatrick bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
345e5dd7070Spatrick   assert(Interface->hasExternalLexicalStorage() ||
346e5dd7070Spatrick          Interface->hasExternalVisibleStorage());
347e5dd7070Spatrick   bool FoundMatchingDC = false;
348e5dd7070Spatrick   ForEachMatchingDC(Interface,
349e5dd7070Spatrick                     [&](ASTImporter &Forward, ASTImporter &Reverse,
350e5dd7070Spatrick                         Source<const DeclContext *> SourceDC) -> bool {
351e5dd7070Spatrick                       FoundMatchingDC = true;
352e5dd7070Spatrick                       return true;
353e5dd7070Spatrick                     });
354e5dd7070Spatrick   return FoundMatchingDC;
355e5dd7070Spatrick }
356e5dd7070Spatrick 
357e5dd7070Spatrick namespace {
IsSameDC(const DeclContext * D1,const DeclContext * D2)358e5dd7070Spatrick bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
359e5dd7070Spatrick   if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
360e5dd7070Spatrick     return true; // There are many cases where Objective-C is ambiguous.
361e5dd7070Spatrick   if (auto *T1 = dyn_cast<TagDecl>(D1))
362e5dd7070Spatrick     if (auto *T2 = dyn_cast<TagDecl>(D2))
363e5dd7070Spatrick       if (T1->getFirstDecl() == T2->getFirstDecl())
364e5dd7070Spatrick         return true;
365e5dd7070Spatrick   return D1 == D2 || D1 == CanonicalizeDC(D2);
366e5dd7070Spatrick }
367e5dd7070Spatrick }
368e5dd7070Spatrick 
MaybeRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)369e5dd7070Spatrick void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
370e5dd7070Spatrick                                           DCOrigin Origin) {
371e5dd7070Spatrick   LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
372e5dd7070Spatrick   ASTImporter &Reverse = Importer.GetReverse();
373e5dd7070Spatrick   Source<const DeclContext *> FoundFromDC =
374e5dd7070Spatrick       LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
375e5dd7070Spatrick   const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
376e5dd7070Spatrick   if (DoRecord)
377e5dd7070Spatrick     RecordOriginImpl(ToDC, Origin, Importer);
378e5dd7070Spatrick   if (LoggingEnabled())
379e5dd7070Spatrick     logs() << "(ExternalASTMerger*)" << (void*)this
380e5dd7070Spatrick              << (DoRecord ? " decided " : " decided NOT")
381e5dd7070Spatrick              << " to record origin (DeclContext*)" << (void*)Origin.DC
382e5dd7070Spatrick              << ", (ASTContext*)" << (void*)&Origin.AST
383e5dd7070Spatrick              << "\n";
384e5dd7070Spatrick }
385e5dd7070Spatrick 
ForceRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)386e5dd7070Spatrick void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
387e5dd7070Spatrick                                           DCOrigin Origin) {
388e5dd7070Spatrick   RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
389e5dd7070Spatrick }
390e5dd7070Spatrick 
RecordOriginImpl(const DeclContext * ToDC,DCOrigin Origin,ASTImporter & Importer)391e5dd7070Spatrick void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
392e5dd7070Spatrick                                          ASTImporter &Importer) {
393e5dd7070Spatrick   Origins[ToDC] = Origin;
394e5dd7070Spatrick   Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
395e5dd7070Spatrick }
396e5dd7070Spatrick 
ExternalASTMerger(const ImporterTarget & Target,llvm::ArrayRef<ImporterSource> Sources)397e5dd7070Spatrick ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
398e5dd7070Spatrick                                      llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
399e5dd7070Spatrick   SharedState = std::make_shared<ASTImporterSharedState>(
400e5dd7070Spatrick       *Target.AST.getTranslationUnitDecl());
401e5dd7070Spatrick   AddSources(Sources);
402e5dd7070Spatrick }
403e5dd7070Spatrick 
FindOriginalDecl(Decl * D)404e5dd7070Spatrick Decl *ExternalASTMerger::FindOriginalDecl(Decl *D) {
405e5dd7070Spatrick   assert(&D->getASTContext() == &Target.AST);
406e5dd7070Spatrick   for (const auto &I : Importers)
407e5dd7070Spatrick     if (auto Result = I->GetOriginalDecl(D))
408e5dd7070Spatrick       return Result;
409e5dd7070Spatrick   return nullptr;
410e5dd7070Spatrick }
411e5dd7070Spatrick 
AddSources(llvm::ArrayRef<ImporterSource> Sources)412e5dd7070Spatrick void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
413e5dd7070Spatrick   for (const ImporterSource &S : Sources) {
414e5dd7070Spatrick     assert(&S.getASTContext() != &Target.AST);
415e5dd7070Spatrick     // Check that the associated merger actually imports into the source AST.
416e5dd7070Spatrick     assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.getASTContext());
417e5dd7070Spatrick     Importers.push_back(std::make_unique<LazyASTImporter>(
418e5dd7070Spatrick         *this, Target.AST, Target.FM, S, SharedState));
419e5dd7070Spatrick   }
420e5dd7070Spatrick }
421e5dd7070Spatrick 
RemoveSources(llvm::ArrayRef<ImporterSource> Sources)422e5dd7070Spatrick void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
423e5dd7070Spatrick   if (LoggingEnabled())
424e5dd7070Spatrick     for (const ImporterSource &S : Sources)
425e5dd7070Spatrick       logs() << "(ExternalASTMerger*)" << (void *)this
426e5dd7070Spatrick              << " removing source (ASTContext*)" << (void *)&S.getASTContext()
427e5dd7070Spatrick              << "\n";
428*12c85518Srobert   llvm::erase_if(Importers,
429e5dd7070Spatrick                  [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
430e5dd7070Spatrick                    for (const ImporterSource &S : Sources) {
431e5dd7070Spatrick                      if (&Importer->getFromContext() == &S.getASTContext())
432e5dd7070Spatrick                        return true;
433e5dd7070Spatrick                    }
434e5dd7070Spatrick                    return false;
435*12c85518Srobert                  });
436e5dd7070Spatrick   for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
437e5dd7070Spatrick     std::pair<const DeclContext *, DCOrigin> Origin = *OI;
438e5dd7070Spatrick     bool Erase = false;
439e5dd7070Spatrick     for (const ImporterSource &S : Sources) {
440e5dd7070Spatrick       if (&S.getASTContext() == Origin.second.AST) {
441e5dd7070Spatrick         Erase = true;
442e5dd7070Spatrick         break;
443e5dd7070Spatrick       }
444e5dd7070Spatrick     }
445e5dd7070Spatrick     if (Erase)
446e5dd7070Spatrick       OI = Origins.erase(OI);
447e5dd7070Spatrick     else
448e5dd7070Spatrick       ++OI;
449e5dd7070Spatrick   }
450e5dd7070Spatrick }
451e5dd7070Spatrick 
452e5dd7070Spatrick template <typename DeclTy>
importSpecializations(DeclTy * D,ASTImporter * Importer)453e5dd7070Spatrick static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
454e5dd7070Spatrick   for (auto *Spec : D->specializations()) {
455e5dd7070Spatrick     auto ImportedSpecOrError = Importer->Import(Spec);
456e5dd7070Spatrick     if (!ImportedSpecOrError) {
457e5dd7070Spatrick       llvm::consumeError(ImportedSpecOrError.takeError());
458e5dd7070Spatrick       return true;
459e5dd7070Spatrick     }
460e5dd7070Spatrick   }
461e5dd7070Spatrick   return false;
462e5dd7070Spatrick }
463e5dd7070Spatrick 
464e5dd7070Spatrick /// Imports specializations from template declarations that can be specialized.
importSpecializationsIfNeeded(Decl * D,ASTImporter * Importer)465e5dd7070Spatrick static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
466e5dd7070Spatrick   if (!isa<TemplateDecl>(D))
467e5dd7070Spatrick     return false;
468e5dd7070Spatrick   if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
469e5dd7070Spatrick     return importSpecializations(FunctionTD, Importer);
470e5dd7070Spatrick   else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
471e5dd7070Spatrick     return importSpecializations(ClassTD, Importer);
472e5dd7070Spatrick   else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
473e5dd7070Spatrick     return importSpecializations(VarTD, Importer);
474e5dd7070Spatrick   return false;
475e5dd7070Spatrick }
476e5dd7070Spatrick 
FindExternalVisibleDeclsByName(const DeclContext * DC,DeclarationName Name)477e5dd7070Spatrick bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
478e5dd7070Spatrick                                                        DeclarationName Name) {
479e5dd7070Spatrick   llvm::SmallVector<NamedDecl *, 1> Decls;
480e5dd7070Spatrick   llvm::SmallVector<Candidate, 4> Candidates;
481e5dd7070Spatrick 
482e5dd7070Spatrick   auto FilterFoundDecl = [&Candidates](const Candidate &C) {
483e5dd7070Spatrick    if (!HasDeclOfSameType(Candidates, C))
484e5dd7070Spatrick      Candidates.push_back(C);
485e5dd7070Spatrick   };
486e5dd7070Spatrick 
487e5dd7070Spatrick   ForEachMatchingDC(DC,
488e5dd7070Spatrick                     [&](ASTImporter &Forward, ASTImporter &Reverse,
489e5dd7070Spatrick                         Source<const DeclContext *> SourceDC) -> bool {
490e5dd7070Spatrick                       auto FromNameOrErr = Reverse.Import(Name);
491e5dd7070Spatrick                       if (!FromNameOrErr) {
492e5dd7070Spatrick                         llvm::consumeError(FromNameOrErr.takeError());
493e5dd7070Spatrick                         return false;
494e5dd7070Spatrick                       }
495e5dd7070Spatrick                       DeclContextLookupResult Result =
496e5dd7070Spatrick                           SourceDC.get()->lookup(*FromNameOrErr);
497e5dd7070Spatrick                       for (NamedDecl *FromD : Result) {
498e5dd7070Spatrick                         FilterFoundDecl(std::make_pair(FromD, &Forward));
499e5dd7070Spatrick                       }
500e5dd7070Spatrick                       return false;
501e5dd7070Spatrick                     });
502e5dd7070Spatrick 
503e5dd7070Spatrick   if (Candidates.empty())
504e5dd7070Spatrick     return false;
505e5dd7070Spatrick 
506e5dd7070Spatrick   Decls.reserve(Candidates.size());
507e5dd7070Spatrick   for (const Candidate &C : Candidates) {
508e5dd7070Spatrick     Decl *LookupRes = C.first.get();
509e5dd7070Spatrick     ASTImporter *Importer = C.second;
510e5dd7070Spatrick     auto NDOrErr = Importer->Import(LookupRes);
511e5dd7070Spatrick     NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
512e5dd7070Spatrick     assert(ND);
513e5dd7070Spatrick     // If we don't import specialization, they are not available via lookup
514e5dd7070Spatrick     // because the lookup result is imported TemplateDecl and it does not
515e5dd7070Spatrick     // reference its specializations until they are imported explicitly.
516e5dd7070Spatrick     bool IsSpecImportFailed =
517e5dd7070Spatrick         importSpecializationsIfNeeded(LookupRes, Importer);
518e5dd7070Spatrick     assert(!IsSpecImportFailed);
519e5dd7070Spatrick     (void)IsSpecImportFailed;
520e5dd7070Spatrick     Decls.push_back(ND);
521e5dd7070Spatrick   }
522e5dd7070Spatrick   SetExternalVisibleDeclsForName(DC, Name, Decls);
523e5dd7070Spatrick   return true;
524e5dd7070Spatrick }
525e5dd7070Spatrick 
FindExternalLexicalDecls(const DeclContext * DC,llvm::function_ref<bool (Decl::Kind)> IsKindWeWant,SmallVectorImpl<Decl * > & Result)526e5dd7070Spatrick void ExternalASTMerger::FindExternalLexicalDecls(
527e5dd7070Spatrick     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
528e5dd7070Spatrick     SmallVectorImpl<Decl *> &Result) {
529e5dd7070Spatrick   ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
530e5dd7070Spatrick                             Source<const DeclContext *> SourceDC) -> bool {
531e5dd7070Spatrick     for (const Decl *SourceDecl : SourceDC.get()->decls()) {
532e5dd7070Spatrick       if (IsKindWeWant(SourceDecl->getKind())) {
533e5dd7070Spatrick         auto ImportedDeclOrErr = Forward.Import(SourceDecl);
534e5dd7070Spatrick         if (ImportedDeclOrErr)
535e5dd7070Spatrick           assert(!(*ImportedDeclOrErr) ||
536e5dd7070Spatrick                  IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
537e5dd7070Spatrick         else
538e5dd7070Spatrick           llvm::consumeError(ImportedDeclOrErr.takeError());
539e5dd7070Spatrick       }
540e5dd7070Spatrick     }
541e5dd7070Spatrick     return false;
542e5dd7070Spatrick   });
543e5dd7070Spatrick }
544e5dd7070Spatrick 
545