xref: /freebsd/contrib/llvm-project/clang/lib/AST/ExternalASTMerger.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements the ExternalASTMerger, which vends a combination of
100b57cec5SDimitry Andric //  ASTs from several different ASTContext/FileManager pairs
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/Decl.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
190b57cec5SDimitry Andric #include "clang/AST/ExternalASTMerger.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace clang;
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric namespace {
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric template <typename T> struct Source {
260b57cec5SDimitry Andric   T t;
Source__anonb979a45e0111::Source270b57cec5SDimitry Andric   Source(T t) : t(t) {}
operator T__anonb979a45e0111::Source280b57cec5SDimitry Andric   operator T() { return t; }
get__anonb979a45e0111::Source290b57cec5SDimitry Andric   template <typename U = T> U &get() { return t; }
get__anonb979a45e0111::Source300b57cec5SDimitry Andric   template <typename U = T> const U &get() const { return t; }
operator Source<U>__anonb979a45e0111::Source310b57cec5SDimitry Andric   template <typename U> operator Source<U>() { return Source<U>(t); }
320b57cec5SDimitry Andric };
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric /// For the given DC, return the DC that is safe to perform lookups on.  This is
370b57cec5SDimitry Andric /// the DC we actually want to work with most of the time.
CanonicalizeDC(const DeclContext * DC)380b57cec5SDimitry Andric const DeclContext *CanonicalizeDC(const DeclContext *DC) {
390b57cec5SDimitry Andric   if (isa<LinkageSpecDecl>(DC))
400b57cec5SDimitry Andric     return DC->getRedeclContext();
410b57cec5SDimitry Andric   return DC;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric Source<const DeclContext *>
LookupSameContext(Source<TranslationUnitDecl * > SourceTU,const DeclContext * DC,ASTImporter & ReverseImporter)450b57cec5SDimitry Andric LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
460b57cec5SDimitry Andric                   ASTImporter &ReverseImporter) {
470b57cec5SDimitry Andric   DC = CanonicalizeDC(DC);
480b57cec5SDimitry Andric   if (DC->isTranslationUnit()) {
490b57cec5SDimitry Andric     return SourceTU;
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   Source<const DeclContext *> SourceParentDC =
520b57cec5SDimitry Andric       LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
530b57cec5SDimitry Andric   if (!SourceParentDC) {
540b57cec5SDimitry Andric     // If we couldn't find the parent DC in this TranslationUnit, give up.
550b57cec5SDimitry Andric     return nullptr;
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric   auto *ND = cast<NamedDecl>(DC);
580b57cec5SDimitry Andric   DeclarationName Name = ND->getDeclName();
590b57cec5SDimitry Andric   auto SourceNameOrErr = ReverseImporter.Import(Name);
600b57cec5SDimitry Andric   if (!SourceNameOrErr) {
610b57cec5SDimitry Andric     llvm::consumeError(SourceNameOrErr.takeError());
620b57cec5SDimitry Andric     return nullptr;
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric   Source<DeclarationName> SourceName = *SourceNameOrErr;
650b57cec5SDimitry Andric   DeclContext::lookup_result SearchResult =
660b57cec5SDimitry Andric       SourceParentDC.get()->lookup(SourceName.get());
67fe6060f1SDimitry Andric 
680b57cec5SDimitry Andric   // There are two cases here. First, we might not find the name.
690b57cec5SDimitry Andric   // We might also find multiple copies, in which case we have no
700b57cec5SDimitry Andric   // guarantee that the one we wanted is the one we pick.  (E.g.,
710b57cec5SDimitry Andric   // if we have two specializations of the same template it is
720b57cec5SDimitry Andric   // very hard to determine which is the one you want.)
730b57cec5SDimitry Andric   //
740b57cec5SDimitry Andric   // The Origins map fixes this problem by allowing the origin to be
750b57cec5SDimitry Andric   // explicitly recorded, so we trigger that recording by returning
760b57cec5SDimitry Andric   // nothing (rather than a possibly-inaccurate guess) here.
77fe6060f1SDimitry Andric   if (SearchResult.isSingleResult()) {
78fe6060f1SDimitry Andric     NamedDecl *SearchResultDecl = SearchResult.front();
790b57cec5SDimitry Andric     if (isa<DeclContext>(SearchResultDecl) &&
800b57cec5SDimitry Andric         SearchResultDecl->getKind() == DC->getDeclKind())
810b57cec5SDimitry Andric       return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
820b57cec5SDimitry Andric     return nullptr; // This type of lookup is unsupported
83fe6060f1SDimitry Andric   } else {
84fe6060f1SDimitry Andric     return nullptr;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
890b57cec5SDimitry Andric ///
900b57cec5SDimitry Andric /// There are several modifications:
910b57cec5SDimitry Andric ///
920b57cec5SDimitry Andric /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
930b57cec5SDimitry Andric ///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
940b57cec5SDimitry Andric ///   forces MinimalImport to true, which is necessary to make this work.
950b57cec5SDimitry Andric /// - It maintains a reverse importer for use with names.  This allows lookup of
960b57cec5SDimitry Andric ///   arbitrary names in the source context.
970b57cec5SDimitry Andric /// - It updates the ExternalASTMerger's origin map as needed whenever a
980b57cec5SDimitry Andric ///   it sees a DeclContext.
990b57cec5SDimitry Andric class LazyASTImporter : public ASTImporter {
1000b57cec5SDimitry Andric private:
1010b57cec5SDimitry Andric   ExternalASTMerger &Parent;
1020b57cec5SDimitry Andric   ASTImporter Reverse;
1030b57cec5SDimitry Andric   const ExternalASTMerger::OriginMap &FromOrigins;
104a7dea167SDimitry Andric   /// @see ExternalASTMerger::ImporterSource::Temporary
105a7dea167SDimitry Andric   bool TemporarySource;
106a7dea167SDimitry Andric   /// Map of imported declarations back to the declarations they originated
107a7dea167SDimitry Andric   /// from.
108a7dea167SDimitry Andric   llvm::DenseMap<Decl *, Decl *> ToOrigin;
109a7dea167SDimitry Andric   /// @see ExternalASTMerger::ImporterSource::Merger
110a7dea167SDimitry Andric   ExternalASTMerger *SourceMerger;
logs()1110b57cec5SDimitry Andric   llvm::raw_ostream &logs() { return Parent.logs(); }
1120b57cec5SDimitry Andric public:
LazyASTImporter(ExternalASTMerger & _Parent,ASTContext & ToContext,FileManager & ToFileManager,const ExternalASTMerger::ImporterSource & S,std::shared_ptr<ASTImporterSharedState> SharedState)1130b57cec5SDimitry Andric   LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
114a7dea167SDimitry Andric                   FileManager &ToFileManager,
115a7dea167SDimitry Andric                   const ExternalASTMerger::ImporterSource &S,
116a7dea167SDimitry Andric                   std::shared_ptr<ASTImporterSharedState> SharedState)
117a7dea167SDimitry Andric       : ASTImporter(ToContext, ToFileManager, S.getASTContext(),
118a7dea167SDimitry Andric                     S.getFileManager(),
119a7dea167SDimitry Andric                     /*MinimalImport=*/true, SharedState),
120a7dea167SDimitry Andric         Parent(_Parent),
121a7dea167SDimitry Andric         Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager,
1220b57cec5SDimitry Andric                 /*MinimalImport=*/true),
123a7dea167SDimitry Andric         FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()),
124a7dea167SDimitry Andric         SourceMerger(S.getMerger()) {}
125a7dea167SDimitry Andric 
ImportImpl(Decl * FromD)126a7dea167SDimitry Andric   llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
127a7dea167SDimitry Andric     if (!TemporarySource || !SourceMerger)
128a7dea167SDimitry Andric       return ASTImporter::ImportImpl(FromD);
129a7dea167SDimitry Andric 
130a7dea167SDimitry Andric     // If we get here, then this source is importing from a temporary ASTContext
131a7dea167SDimitry Andric     // that also has another ExternalASTMerger attached. It could be
132a7dea167SDimitry Andric     // possible that the current ExternalASTMerger and the temporary ASTContext
133a7dea167SDimitry Andric     // share a common ImporterSource, which means that the temporary
134a7dea167SDimitry Andric     // AST could contain declarations that were imported from a source
135a7dea167SDimitry Andric     // that this ExternalASTMerger can access directly. Instead of importing
136a7dea167SDimitry Andric     // such declarations from the temporary ASTContext, they should instead
137a7dea167SDimitry Andric     // be directly imported by this ExternalASTMerger from the original
138a7dea167SDimitry Andric     // source. This way the ExternalASTMerger can safely do a minimal import
139a7dea167SDimitry Andric     // without creating incomplete declarations originated from a temporary
140a7dea167SDimitry Andric     // ASTContext. If we would try to complete such declarations later on, we
141a7dea167SDimitry Andric     // would fail to do so as their temporary AST could be deleted (which means
142a7dea167SDimitry Andric     // that the missing parts of the minimally imported declaration in that
143a7dea167SDimitry Andric     // ASTContext were also deleted).
144a7dea167SDimitry Andric     //
145a7dea167SDimitry Andric     // The following code tracks back any declaration that needs to be
146a7dea167SDimitry Andric     // imported from the temporary ASTContext to a persistent ASTContext.
147a7dea167SDimitry Andric     // Then the ExternalASTMerger tries to import from the persistent
148a7dea167SDimitry Andric     // ASTContext directly by using the associated ASTImporter. If that
149a7dea167SDimitry Andric     // succeeds, this ASTImporter just maps the declarations imported by
150a7dea167SDimitry Andric     // the other (persistent) ASTImporter to this (temporary) ASTImporter.
151a7dea167SDimitry Andric     // The steps can be visualized like this:
152a7dea167SDimitry Andric     //
153a7dea167SDimitry Andric     //  Target AST <--- 3. Indirect import --- Persistent AST
154a7dea167SDimitry Andric     //       ^            of persistent decl        ^
155a7dea167SDimitry Andric     //       |                                      |
156a7dea167SDimitry Andric     // 1. Current import           2. Tracking back to persistent decl
157a7dea167SDimitry Andric     // 4. Map persistent decl                       |
158a7dea167SDimitry Andric     //  & pretend we imported.                      |
159a7dea167SDimitry Andric     //       |                                      |
160a7dea167SDimitry Andric     // Temporary AST -------------------------------'
161a7dea167SDimitry Andric 
162a7dea167SDimitry Andric     // First, ask the ExternalASTMerger of the source where the temporary
163a7dea167SDimitry Andric     // declaration originated from.
164a7dea167SDimitry Andric     Decl *Persistent = SourceMerger->FindOriginalDecl(FromD);
165a7dea167SDimitry Andric     // FromD isn't from a persistent AST, so just do a normal import.
166a7dea167SDimitry Andric     if (!Persistent)
167a7dea167SDimitry Andric       return ASTImporter::ImportImpl(FromD);
168a7dea167SDimitry Andric     // Now ask the current ExternalASTMerger to try import the persistent
169a7dea167SDimitry Andric     // declaration into the target.
170a7dea167SDimitry Andric     ASTContext &PersistentCtx = Persistent->getASTContext();
171a7dea167SDimitry Andric     ASTImporter &OtherImporter = Parent.ImporterForOrigin(PersistentCtx);
172a7dea167SDimitry Andric     // Check that we never end up in the current Importer again.
173a7dea167SDimitry Andric     assert((&PersistentCtx != &getFromContext()) && (&OtherImporter != this) &&
174a7dea167SDimitry Andric            "Delegated to same Importer?");
175a7dea167SDimitry Andric     auto DeclOrErr = OtherImporter.Import(Persistent);
176a7dea167SDimitry Andric     // Errors when importing the persistent decl are treated as if we
177a7dea167SDimitry Andric     // had errors with importing the temporary decl.
178a7dea167SDimitry Andric     if (!DeclOrErr)
179a7dea167SDimitry Andric       return DeclOrErr.takeError();
180a7dea167SDimitry Andric     Decl *D = *DeclOrErr;
181a7dea167SDimitry Andric     // Tell the current ASTImporter that this has already been imported
182a7dea167SDimitry Andric     // to prevent any further queries for the temporary decl.
183a7dea167SDimitry Andric     MapImported(FromD, D);
184a7dea167SDimitry Andric     return D;
185a7dea167SDimitry Andric   }
186a7dea167SDimitry Andric 
187a7dea167SDimitry Andric   /// Implements the ASTImporter interface for tracking back a declaration
188a7dea167SDimitry Andric   /// to its original declaration it came from.
GetOriginalDecl(Decl * To)189a7dea167SDimitry Andric   Decl *GetOriginalDecl(Decl *To) override {
190*06c3fb27SDimitry Andric     return ToOrigin.lookup(To);
191a7dea167SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
1940b57cec5SDimitry Andric   /// map is kept up to date.  Also set the appropriate flags.
Imported(Decl * From,Decl * To)1950b57cec5SDimitry Andric   void Imported(Decl *From, Decl *To) override {
196a7dea167SDimitry Andric     ToOrigin[To] = From;
197a7dea167SDimitry Andric 
1980b57cec5SDimitry Andric     if (auto *ToDC = dyn_cast<DeclContext>(To)) {
1990b57cec5SDimitry Andric       const bool LoggingEnabled = Parent.LoggingEnabled();
2000b57cec5SDimitry Andric       if (LoggingEnabled)
2010b57cec5SDimitry Andric         logs() << "(ExternalASTMerger*)" << (void*)&Parent
2020b57cec5SDimitry Andric                << " imported (DeclContext*)" << (void*)ToDC
2030b57cec5SDimitry Andric                << ", (ASTContext*)" << (void*)&getToContext()
2040b57cec5SDimitry Andric                << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
2050b57cec5SDimitry Andric                << ", (ASTContext*)" << (void*)&getFromContext()
2060b57cec5SDimitry Andric                << "\n";
2070b57cec5SDimitry Andric       Source<DeclContext *> FromDC(
2080b57cec5SDimitry Andric           cast<DeclContext>(From)->getPrimaryContext());
2090b57cec5SDimitry Andric       if (FromOrigins.count(FromDC) &&
2100b57cec5SDimitry Andric           Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
2110b57cec5SDimitry Andric         if (LoggingEnabled)
2120b57cec5SDimitry Andric           logs() << "(ExternalASTMerger*)" << (void*)&Parent
2130b57cec5SDimitry Andric                  << " forced origin (DeclContext*)"
2140b57cec5SDimitry Andric                  << (void*)FromOrigins.at(FromDC).DC
2150b57cec5SDimitry Andric                  << ", (ASTContext*)"
2160b57cec5SDimitry Andric                  << (void*)FromOrigins.at(FromDC).AST
2170b57cec5SDimitry Andric                  << "\n";
2180b57cec5SDimitry Andric         Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
2190b57cec5SDimitry Andric       } else {
2200b57cec5SDimitry Andric         if (LoggingEnabled)
2210b57cec5SDimitry Andric           logs() << "(ExternalASTMerger*)" << (void*)&Parent
2220b57cec5SDimitry Andric                  << " maybe recording origin (DeclContext*)" << (void*)FromDC
2230b57cec5SDimitry Andric                  << ", (ASTContext*)" << (void*)&getFromContext()
2240b57cec5SDimitry Andric                  << "\n";
2250b57cec5SDimitry Andric         Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
2260b57cec5SDimitry Andric       }
2270b57cec5SDimitry Andric     }
2280b57cec5SDimitry Andric     if (auto *ToTag = dyn_cast<TagDecl>(To)) {
2290b57cec5SDimitry Andric       ToTag->setHasExternalLexicalStorage();
2300b57cec5SDimitry Andric       ToTag->getPrimaryContext()->setMustBuildLookupTable();
2310b57cec5SDimitry Andric       assert(Parent.CanComplete(ToTag));
2320b57cec5SDimitry Andric     } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
2330b57cec5SDimitry Andric       ToNamespace->setHasExternalVisibleStorage();
2340b57cec5SDimitry Andric       assert(Parent.CanComplete(ToNamespace));
2350b57cec5SDimitry Andric     } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
2360b57cec5SDimitry Andric       ToContainer->setHasExternalLexicalStorage();
2370b57cec5SDimitry Andric       ToContainer->getPrimaryContext()->setMustBuildLookupTable();
2380b57cec5SDimitry Andric       assert(Parent.CanComplete(ToContainer));
2390b57cec5SDimitry Andric     }
2400b57cec5SDimitry Andric   }
GetReverse()2410b57cec5SDimitry Andric   ASTImporter &GetReverse() { return Reverse; }
2420b57cec5SDimitry Andric };
2430b57cec5SDimitry Andric 
HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls,const Candidate & C)2440b57cec5SDimitry Andric bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
2450b57cec5SDimitry Andric   if (isa<FunctionDecl>(C.first.get()))
2460b57cec5SDimitry Andric     return false;
2470b57cec5SDimitry Andric   return llvm::any_of(Decls, [&](const Candidate &D) {
2480b57cec5SDimitry Andric     return C.first.get()->getKind() == D.first.get()->getKind();
2490b57cec5SDimitry Andric   });
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric } // end namespace
2530b57cec5SDimitry Andric 
ImporterForOrigin(ASTContext & OriginContext)2540b57cec5SDimitry Andric ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
2550b57cec5SDimitry Andric   for (const std::unique_ptr<ASTImporter> &I : Importers)
2560b57cec5SDimitry Andric     if (&I->getFromContext() == &OriginContext)
2570b57cec5SDimitry Andric       return *I;
2580b57cec5SDimitry Andric   llvm_unreachable("We should have an importer for this origin!");
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric namespace {
LazyImporterForOrigin(ExternalASTMerger & Merger,ASTContext & OriginContext)2620b57cec5SDimitry Andric LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
2630b57cec5SDimitry Andric                                    ASTContext &OriginContext) {
2640b57cec5SDimitry Andric   return static_cast<LazyASTImporter &>(
2650b57cec5SDimitry Andric       Merger.ImporterForOrigin(OriginContext));
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric 
HasImporterForOrigin(ASTContext & OriginContext)2690b57cec5SDimitry Andric bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
2700b57cec5SDimitry Andric   for (const std::unique_ptr<ASTImporter> &I : Importers)
2710b57cec5SDimitry Andric     if (&I->getFromContext() == &OriginContext)
2720b57cec5SDimitry Andric       return true;
2730b57cec5SDimitry Andric   return false;
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric template <typename CallbackType>
ForEachMatchingDC(const DeclContext * DC,CallbackType Callback)2770b57cec5SDimitry Andric void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
2780b57cec5SDimitry Andric                                           CallbackType Callback) {
2790b57cec5SDimitry Andric   if (Origins.count(DC)) {
2800b57cec5SDimitry Andric     ExternalASTMerger::DCOrigin Origin = Origins[DC];
2810b57cec5SDimitry Andric     LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
2820b57cec5SDimitry Andric     Callback(Importer, Importer.GetReverse(), Origin.DC);
2830b57cec5SDimitry Andric   } else {
2840b57cec5SDimitry Andric     bool DidCallback = false;
2850b57cec5SDimitry Andric     for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
2860b57cec5SDimitry Andric       Source<TranslationUnitDecl *> SourceTU =
2870b57cec5SDimitry Andric           Importer->getFromContext().getTranslationUnitDecl();
2880b57cec5SDimitry Andric       ASTImporter &Reverse =
2890b57cec5SDimitry Andric           static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
2900b57cec5SDimitry Andric       if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
2910b57cec5SDimitry Andric         DidCallback = true;
2920b57cec5SDimitry Andric         if (Callback(*Importer, Reverse, SourceDC))
2930b57cec5SDimitry Andric           break;
2940b57cec5SDimitry Andric       }
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric     if (!DidCallback && LoggingEnabled())
2970b57cec5SDimitry Andric       logs() << "(ExternalASTMerger*)" << (void*)this
2980b57cec5SDimitry Andric              << " asserting for (DeclContext*)" << (const void*)DC
2990b57cec5SDimitry Andric              << ", (ASTContext*)" << (void*)&Target.AST
3000b57cec5SDimitry Andric              << "\n";
3010b57cec5SDimitry Andric     assert(DidCallback && "Couldn't find a source context matching our DC");
3020b57cec5SDimitry Andric   }
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric 
CompleteType(TagDecl * Tag)3050b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(TagDecl *Tag) {
3060b57cec5SDimitry Andric   assert(Tag->hasExternalLexicalStorage());
3070b57cec5SDimitry Andric   ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
3080b57cec5SDimitry Andric                              Source<const DeclContext *> SourceDC) -> bool {
3090b57cec5SDimitry Andric     auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
3100b57cec5SDimitry Andric     if (SourceTag->hasExternalLexicalStorage())
3110b57cec5SDimitry Andric       SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
3120b57cec5SDimitry Andric     if (!SourceTag->getDefinition())
3130b57cec5SDimitry Andric       return false;
3140b57cec5SDimitry Andric     Forward.MapImported(SourceTag, Tag);
3150b57cec5SDimitry Andric     if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
3160b57cec5SDimitry Andric       llvm::consumeError(std::move(Err));
3170b57cec5SDimitry Andric     Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
3180b57cec5SDimitry Andric     return true;
3190b57cec5SDimitry Andric   });
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
CompleteType(ObjCInterfaceDecl * Interface)3220b57cec5SDimitry Andric void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
3230b57cec5SDimitry Andric   assert(Interface->hasExternalLexicalStorage());
3240b57cec5SDimitry Andric   ForEachMatchingDC(
3250b57cec5SDimitry Andric       Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
3260b57cec5SDimitry Andric                      Source<const DeclContext *> SourceDC) -> bool {
3270b57cec5SDimitry Andric         auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
3280b57cec5SDimitry Andric             cast<ObjCInterfaceDecl>(SourceDC.get()));
3290b57cec5SDimitry Andric         if (SourceInterface->hasExternalLexicalStorage())
3300b57cec5SDimitry Andric           SourceInterface->getASTContext().getExternalSource()->CompleteType(
3310b57cec5SDimitry Andric               SourceInterface);
3320b57cec5SDimitry Andric         if (!SourceInterface->getDefinition())
3330b57cec5SDimitry Andric           return false;
3340b57cec5SDimitry Andric         Forward.MapImported(SourceInterface, Interface);
3350b57cec5SDimitry Andric         if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
3360b57cec5SDimitry Andric           llvm::consumeError(std::move(Err));
3370b57cec5SDimitry Andric         return true;
3380b57cec5SDimitry Andric       });
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
CanComplete(DeclContext * Interface)3410b57cec5SDimitry Andric bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
3420b57cec5SDimitry Andric   assert(Interface->hasExternalLexicalStorage() ||
3430b57cec5SDimitry Andric          Interface->hasExternalVisibleStorage());
3440b57cec5SDimitry Andric   bool FoundMatchingDC = false;
3450b57cec5SDimitry Andric   ForEachMatchingDC(Interface,
3460b57cec5SDimitry Andric                     [&](ASTImporter &Forward, ASTImporter &Reverse,
3470b57cec5SDimitry Andric                         Source<const DeclContext *> SourceDC) -> bool {
3480b57cec5SDimitry Andric                       FoundMatchingDC = true;
3490b57cec5SDimitry Andric                       return true;
3500b57cec5SDimitry Andric                     });
3510b57cec5SDimitry Andric   return FoundMatchingDC;
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric namespace {
IsSameDC(const DeclContext * D1,const DeclContext * D2)3550b57cec5SDimitry Andric bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
3560b57cec5SDimitry Andric   if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
3570b57cec5SDimitry Andric     return true; // There are many cases where Objective-C is ambiguous.
3580b57cec5SDimitry Andric   if (auto *T1 = dyn_cast<TagDecl>(D1))
3590b57cec5SDimitry Andric     if (auto *T2 = dyn_cast<TagDecl>(D2))
3600b57cec5SDimitry Andric       if (T1->getFirstDecl() == T2->getFirstDecl())
3610b57cec5SDimitry Andric         return true;
3620b57cec5SDimitry Andric   return D1 == D2 || D1 == CanonicalizeDC(D2);
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
MaybeRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)3660b57cec5SDimitry Andric void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
3670b57cec5SDimitry Andric                                           DCOrigin Origin) {
3680b57cec5SDimitry Andric   LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
3690b57cec5SDimitry Andric   ASTImporter &Reverse = Importer.GetReverse();
3700b57cec5SDimitry Andric   Source<const DeclContext *> FoundFromDC =
3710b57cec5SDimitry Andric       LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
3720b57cec5SDimitry Andric   const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
3730b57cec5SDimitry Andric   if (DoRecord)
3740b57cec5SDimitry Andric     RecordOriginImpl(ToDC, Origin, Importer);
3750b57cec5SDimitry Andric   if (LoggingEnabled())
3760b57cec5SDimitry Andric     logs() << "(ExternalASTMerger*)" << (void*)this
3770b57cec5SDimitry Andric              << (DoRecord ? " decided " : " decided NOT")
3780b57cec5SDimitry Andric              << " to record origin (DeclContext*)" << (void*)Origin.DC
3790b57cec5SDimitry Andric              << ", (ASTContext*)" << (void*)&Origin.AST
3800b57cec5SDimitry Andric              << "\n";
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
ForceRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)3830b57cec5SDimitry Andric void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
3840b57cec5SDimitry Andric                                           DCOrigin Origin) {
3850b57cec5SDimitry Andric   RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
RecordOriginImpl(const DeclContext * ToDC,DCOrigin Origin,ASTImporter & Importer)3880b57cec5SDimitry Andric void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
3890b57cec5SDimitry Andric                                          ASTImporter &Importer) {
3900b57cec5SDimitry Andric   Origins[ToDC] = Origin;
3910b57cec5SDimitry Andric   Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
ExternalASTMerger(const ImporterTarget & Target,llvm::ArrayRef<ImporterSource> Sources)3940b57cec5SDimitry Andric ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
3950b57cec5SDimitry Andric                                      llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
396a7dea167SDimitry Andric   SharedState = std::make_shared<ASTImporterSharedState>(
397a7dea167SDimitry Andric       *Target.AST.getTranslationUnitDecl());
3980b57cec5SDimitry Andric   AddSources(Sources);
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
FindOriginalDecl(Decl * D)401a7dea167SDimitry Andric Decl *ExternalASTMerger::FindOriginalDecl(Decl *D) {
402a7dea167SDimitry Andric   assert(&D->getASTContext() == &Target.AST);
403a7dea167SDimitry Andric   for (const auto &I : Importers)
404a7dea167SDimitry Andric     if (auto Result = I->GetOriginalDecl(D))
405a7dea167SDimitry Andric       return Result;
406a7dea167SDimitry Andric   return nullptr;
407a7dea167SDimitry Andric }
408a7dea167SDimitry Andric 
AddSources(llvm::ArrayRef<ImporterSource> Sources)4090b57cec5SDimitry Andric void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
4100b57cec5SDimitry Andric   for (const ImporterSource &S : Sources) {
411a7dea167SDimitry Andric     assert(&S.getASTContext() != &Target.AST);
412a7dea167SDimitry Andric     // Check that the associated merger actually imports into the source AST.
413a7dea167SDimitry Andric     assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.getASTContext());
414a7dea167SDimitry Andric     Importers.push_back(std::make_unique<LazyASTImporter>(
415a7dea167SDimitry Andric         *this, Target.AST, Target.FM, S, SharedState));
4160b57cec5SDimitry Andric   }
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric 
RemoveSources(llvm::ArrayRef<ImporterSource> Sources)4190b57cec5SDimitry Andric void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
4200b57cec5SDimitry Andric   if (LoggingEnabled())
4210b57cec5SDimitry Andric     for (const ImporterSource &S : Sources)
4220b57cec5SDimitry Andric       logs() << "(ExternalASTMerger*)" << (void *)this
423a7dea167SDimitry Andric              << " removing source (ASTContext*)" << (void *)&S.getASTContext()
4240b57cec5SDimitry Andric              << "\n";
425349cc55cSDimitry Andric   llvm::erase_if(Importers,
4260b57cec5SDimitry Andric                  [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
4270b57cec5SDimitry Andric                    for (const ImporterSource &S : Sources) {
428a7dea167SDimitry Andric                      if (&Importer->getFromContext() == &S.getASTContext())
4290b57cec5SDimitry Andric                        return true;
4300b57cec5SDimitry Andric                    }
4310b57cec5SDimitry Andric                    return false;
432349cc55cSDimitry Andric                  });
4330b57cec5SDimitry Andric   for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
4340b57cec5SDimitry Andric     std::pair<const DeclContext *, DCOrigin> Origin = *OI;
4350b57cec5SDimitry Andric     bool Erase = false;
4360b57cec5SDimitry Andric     for (const ImporterSource &S : Sources) {
437a7dea167SDimitry Andric       if (&S.getASTContext() == Origin.second.AST) {
4380b57cec5SDimitry Andric         Erase = true;
4390b57cec5SDimitry Andric         break;
4400b57cec5SDimitry Andric       }
4410b57cec5SDimitry Andric     }
4420b57cec5SDimitry Andric     if (Erase)
4430b57cec5SDimitry Andric       OI = Origins.erase(OI);
4440b57cec5SDimitry Andric     else
4450b57cec5SDimitry Andric       ++OI;
4460b57cec5SDimitry Andric   }
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric template <typename DeclTy>
importSpecializations(DeclTy * D,ASTImporter * Importer)4500b57cec5SDimitry Andric static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
4510b57cec5SDimitry Andric   for (auto *Spec : D->specializations()) {
4520b57cec5SDimitry Andric     auto ImportedSpecOrError = Importer->Import(Spec);
4530b57cec5SDimitry Andric     if (!ImportedSpecOrError) {
4540b57cec5SDimitry Andric       llvm::consumeError(ImportedSpecOrError.takeError());
4550b57cec5SDimitry Andric       return true;
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric   }
4580b57cec5SDimitry Andric   return false;
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric /// Imports specializations from template declarations that can be specialized.
importSpecializationsIfNeeded(Decl * D,ASTImporter * Importer)4620b57cec5SDimitry Andric static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
4630b57cec5SDimitry Andric   if (!isa<TemplateDecl>(D))
4640b57cec5SDimitry Andric     return false;
4650b57cec5SDimitry Andric   if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
4660b57cec5SDimitry Andric     return importSpecializations(FunctionTD, Importer);
4670b57cec5SDimitry Andric   else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
4680b57cec5SDimitry Andric     return importSpecializations(ClassTD, Importer);
4690b57cec5SDimitry Andric   else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
4700b57cec5SDimitry Andric     return importSpecializations(VarTD, Importer);
4710b57cec5SDimitry Andric   return false;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
FindExternalVisibleDeclsByName(const DeclContext * DC,DeclarationName Name)4740b57cec5SDimitry Andric bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
4750b57cec5SDimitry Andric                                                        DeclarationName Name) {
4760b57cec5SDimitry Andric   llvm::SmallVector<NamedDecl *, 1> Decls;
4770b57cec5SDimitry Andric   llvm::SmallVector<Candidate, 4> Candidates;
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric   auto FilterFoundDecl = [&Candidates](const Candidate &C) {
4800b57cec5SDimitry Andric    if (!HasDeclOfSameType(Candidates, C))
4810b57cec5SDimitry Andric      Candidates.push_back(C);
4820b57cec5SDimitry Andric   };
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   ForEachMatchingDC(DC,
4850b57cec5SDimitry Andric                     [&](ASTImporter &Forward, ASTImporter &Reverse,
4860b57cec5SDimitry Andric                         Source<const DeclContext *> SourceDC) -> bool {
4870b57cec5SDimitry Andric                       auto FromNameOrErr = Reverse.Import(Name);
4880b57cec5SDimitry Andric                       if (!FromNameOrErr) {
4890b57cec5SDimitry Andric                         llvm::consumeError(FromNameOrErr.takeError());
4900b57cec5SDimitry Andric                         return false;
4910b57cec5SDimitry Andric                       }
4920b57cec5SDimitry Andric                       DeclContextLookupResult Result =
4930b57cec5SDimitry Andric                           SourceDC.get()->lookup(*FromNameOrErr);
4940b57cec5SDimitry Andric                       for (NamedDecl *FromD : Result) {
4950b57cec5SDimitry Andric                         FilterFoundDecl(std::make_pair(FromD, &Forward));
4960b57cec5SDimitry Andric                       }
4970b57cec5SDimitry Andric                       return false;
4980b57cec5SDimitry Andric                     });
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   if (Candidates.empty())
5010b57cec5SDimitry Andric     return false;
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   Decls.reserve(Candidates.size());
5040b57cec5SDimitry Andric   for (const Candidate &C : Candidates) {
5050b57cec5SDimitry Andric     Decl *LookupRes = C.first.get();
5060b57cec5SDimitry Andric     ASTImporter *Importer = C.second;
5070b57cec5SDimitry Andric     auto NDOrErr = Importer->Import(LookupRes);
508480093f4SDimitry Andric     NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
5090b57cec5SDimitry Andric     assert(ND);
5100b57cec5SDimitry Andric     // If we don't import specialization, they are not available via lookup
5110b57cec5SDimitry Andric     // because the lookup result is imported TemplateDecl and it does not
5120b57cec5SDimitry Andric     // reference its specializations until they are imported explicitly.
5130b57cec5SDimitry Andric     bool IsSpecImportFailed =
5140b57cec5SDimitry Andric         importSpecializationsIfNeeded(LookupRes, Importer);
5150b57cec5SDimitry Andric     assert(!IsSpecImportFailed);
5160b57cec5SDimitry Andric     (void)IsSpecImportFailed;
5170b57cec5SDimitry Andric     Decls.push_back(ND);
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric   SetExternalVisibleDeclsForName(DC, Name, Decls);
5200b57cec5SDimitry Andric   return true;
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
FindExternalLexicalDecls(const DeclContext * DC,llvm::function_ref<bool (Decl::Kind)> IsKindWeWant,SmallVectorImpl<Decl * > & Result)5230b57cec5SDimitry Andric void ExternalASTMerger::FindExternalLexicalDecls(
5240b57cec5SDimitry Andric     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
5250b57cec5SDimitry Andric     SmallVectorImpl<Decl *> &Result) {
5260b57cec5SDimitry Andric   ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
5270b57cec5SDimitry Andric                             Source<const DeclContext *> SourceDC) -> bool {
5280b57cec5SDimitry Andric     for (const Decl *SourceDecl : SourceDC.get()->decls()) {
5290b57cec5SDimitry Andric       if (IsKindWeWant(SourceDecl->getKind())) {
5300b57cec5SDimitry Andric         auto ImportedDeclOrErr = Forward.Import(SourceDecl);
5310b57cec5SDimitry Andric         if (ImportedDeclOrErr)
5320b57cec5SDimitry Andric           assert(!(*ImportedDeclOrErr) ||
5330b57cec5SDimitry Andric                  IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
5340b57cec5SDimitry Andric         else
5350b57cec5SDimitry Andric           llvm::consumeError(ImportedDeclOrErr.takeError());
5360b57cec5SDimitry Andric       }
5370b57cec5SDimitry Andric     }
5380b57cec5SDimitry Andric     return false;
5390b57cec5SDimitry Andric   });
5400b57cec5SDimitry Andric }
541