1b7160ca4SSean Callanan //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
2b7160ca4SSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b7160ca4SSean Callanan //
7b7160ca4SSean Callanan //===----------------------------------------------------------------------===//
8b7160ca4SSean Callanan //
9b7160ca4SSean Callanan //  This file implements the ExternalASTMerger, which vends a combination of
10b7160ca4SSean Callanan //  ASTs from several different ASTContext/FileManager pairs
11b7160ca4SSean Callanan //
12b7160ca4SSean Callanan //===----------------------------------------------------------------------===//
13b7160ca4SSean Callanan 
14b7160ca4SSean Callanan #include "clang/AST/ASTContext.h"
15b7160ca4SSean Callanan #include "clang/AST/Decl.h"
16967d4384SSean Callanan #include "clang/AST/DeclCXX.h"
17b7160ca4SSean Callanan #include "clang/AST/DeclObjC.h"
188fc8510cSAleksei Sidorin #include "clang/AST/DeclTemplate.h"
19b7160ca4SSean Callanan #include "clang/AST/ExternalASTMerger.h"
20b7160ca4SSean Callanan 
21b7160ca4SSean Callanan using namespace clang;
22b7160ca4SSean Callanan 
23b7160ca4SSean Callanan namespace {
24b7160ca4SSean Callanan 
25b7160ca4SSean Callanan template <typename T> struct Source {
26b7160ca4SSean Callanan   T t;
Source__anon14fbbf8e0111::Source27f8edb1deSSean Callanan   Source(T t) : t(t) {}
operator T__anon14fbbf8e0111::Source28b7160ca4SSean Callanan   operator T() { return t; }
get__anon14fbbf8e0111::Source29b7160ca4SSean Callanan   template <typename U = T> U &get() { return t; }
get__anon14fbbf8e0111::Source30b7160ca4SSean Callanan   template <typename U = T> const U &get() const { return t; }
operator Source<U>__anon14fbbf8e0111::Source31b7160ca4SSean Callanan   template <typename U> operator Source<U>() { return Source<U>(t); }
32b7160ca4SSean Callanan };
33b7160ca4SSean Callanan 
34b7160ca4SSean Callanan typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
35b7160ca4SSean Callanan 
36967d4384SSean Callanan /// For the given DC, return the DC that is safe to perform lookups on.  This is
37967d4384SSean Callanan /// the DC we actually want to work with most of the time.
CanonicalizeDC(const DeclContext * DC)38967d4384SSean Callanan const DeclContext *CanonicalizeDC(const DeclContext *DC) {
39967d4384SSean Callanan   if (isa<LinkageSpecDecl>(DC))
40967d4384SSean Callanan     return DC->getRedeclContext();
41967d4384SSean Callanan   return DC;
42b7160ca4SSean Callanan }
43b7160ca4SSean Callanan 
44b7160ca4SSean Callanan Source<const DeclContext *>
LookupSameContext(Source<TranslationUnitDecl * > SourceTU,const DeclContext * DC,ASTImporter & ReverseImporter)45b7160ca4SSean Callanan LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
46b7160ca4SSean Callanan                   ASTImporter &ReverseImporter) {
47967d4384SSean Callanan   DC = CanonicalizeDC(DC);
48b7160ca4SSean Callanan   if (DC->isTranslationUnit()) {
49b7160ca4SSean Callanan     return SourceTU;
50b7160ca4SSean Callanan   }
51b7160ca4SSean Callanan   Source<const DeclContext *> SourceParentDC =
52b7160ca4SSean Callanan       LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
53b7160ca4SSean Callanan   if (!SourceParentDC) {
54b7160ca4SSean Callanan     // If we couldn't find the parent DC in this TranslationUnit, give up.
55b7160ca4SSean Callanan     return nullptr;
56b7160ca4SSean Callanan   }
57967d4384SSean Callanan   auto *ND = cast<NamedDecl>(DC);
58b7160ca4SSean Callanan   DeclarationName Name = ND->getDeclName();
595ac6d490SGabor Marton   auto SourceNameOrErr = ReverseImporter.Import(Name);
60a1f6b103SBalazs Keri   if (!SourceNameOrErr) {
61a1f6b103SBalazs Keri     llvm::consumeError(SourceNameOrErr.takeError());
62a1f6b103SBalazs Keri     return nullptr;
63a1f6b103SBalazs Keri   }
64a1f6b103SBalazs Keri   Source<DeclarationName> SourceName = *SourceNameOrErr;
65b7160ca4SSean Callanan   DeclContext::lookup_result SearchResult =
66b7160ca4SSean Callanan       SourceParentDC.get()->lookup(SourceName.get());
670cb7e7caSVassil Vassilev 
68967d4384SSean Callanan   // There are two cases here. First, we might not find the name.
69967d4384SSean Callanan   // We might also find multiple copies, in which case we have no
70967d4384SSean Callanan   // guarantee that the one we wanted is the one we pick.  (E.g.,
71967d4384SSean Callanan   // if we have two specializations of the same template it is
72967d4384SSean Callanan   // very hard to determine which is the one you want.)
73967d4384SSean Callanan   //
74967d4384SSean Callanan   // The Origins map fixes this problem by allowing the origin to be
75967d4384SSean Callanan   // explicitly recorded, so we trigger that recording by returning
76967d4384SSean Callanan   // nothing (rather than a possibly-inaccurate guess) here.
770cb7e7caSVassil Vassilev   if (SearchResult.isSingleResult()) {
780cb7e7caSVassil Vassilev     NamedDecl *SearchResultDecl = SearchResult.front();
79967d4384SSean Callanan     if (isa<DeclContext>(SearchResultDecl) &&
80967d4384SSean Callanan         SearchResultDecl->getKind() == DC->getDeclKind())
81967d4384SSean Callanan       return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
82967d4384SSean Callanan     return nullptr; // This type of lookup is unsupported
830cb7e7caSVassil Vassilev   } else {
840cb7e7caSVassil Vassilev     return nullptr;
85b7160ca4SSean Callanan   }
86b7160ca4SSean Callanan }
87b7160ca4SSean Callanan 
88967d4384SSean Callanan /// A custom implementation of ASTImporter, for ExternalASTMerger's purposes.
89967d4384SSean Callanan ///
90967d4384SSean Callanan /// There are several modifications:
91967d4384SSean Callanan ///
92967d4384SSean Callanan /// - It enables lazy lookup (via the HasExternalLexicalStorage flag and a few
93967d4384SSean Callanan ///   others), which instructs Clang to refer to ExternalASTMerger.  Also, it
94967d4384SSean Callanan ///   forces MinimalImport to true, which is necessary to make this work.
95967d4384SSean Callanan /// - It maintains a reverse importer for use with names.  This allows lookup of
96967d4384SSean Callanan ///   arbitrary names in the source context.
97967d4384SSean Callanan /// - It updates the ExternalASTMerger's origin map as needed whenever a
98967d4384SSean Callanan ///   it sees a DeclContext.
99967d4384SSean Callanan class LazyASTImporter : public ASTImporter {
100967d4384SSean Callanan private:
101967d4384SSean Callanan   ExternalASTMerger &Parent;
102967d4384SSean Callanan   ASTImporter Reverse;
103967d4384SSean Callanan   const ExternalASTMerger::OriginMap &FromOrigins;
10451e0bbb0SRaphael Isemann   /// @see ExternalASTMerger::ImporterSource::Temporary
10551e0bbb0SRaphael Isemann   bool TemporarySource;
10651e0bbb0SRaphael Isemann   /// Map of imported declarations back to the declarations they originated
10751e0bbb0SRaphael Isemann   /// from.
10851e0bbb0SRaphael Isemann   llvm::DenseMap<Decl *, Decl *> ToOrigin;
10951e0bbb0SRaphael Isemann   /// @see ExternalASTMerger::ImporterSource::Merger
11051e0bbb0SRaphael Isemann   ExternalASTMerger *SourceMerger;
logs()111967d4384SSean Callanan   llvm::raw_ostream &logs() { return Parent.logs(); }
112967d4384SSean Callanan public:
LazyASTImporter(ExternalASTMerger & _Parent,ASTContext & ToContext,FileManager & ToFileManager,const ExternalASTMerger::ImporterSource & S,std::shared_ptr<ASTImporterSharedState> SharedState)113967d4384SSean Callanan   LazyASTImporter(ExternalASTMerger &_Parent, ASTContext &ToContext,
114cf628714SRaphael Isemann                   FileManager &ToFileManager,
11551e0bbb0SRaphael Isemann                   const ExternalASTMerger::ImporterSource &S,
116e7714fe7SRaphael Isemann                   std::shared_ptr<ASTImporterSharedState> SharedState)
11751e0bbb0SRaphael Isemann       : ASTImporter(ToContext, ToFileManager, S.getASTContext(),
11851e0bbb0SRaphael Isemann                     S.getFileManager(),
119e7714fe7SRaphael Isemann                     /*MinimalImport=*/true, SharedState),
120cf628714SRaphael Isemann         Parent(_Parent),
12151e0bbb0SRaphael Isemann         Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager,
12251e0bbb0SRaphael Isemann                 /*MinimalImport=*/true),
12351e0bbb0SRaphael Isemann         FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()),
12451e0bbb0SRaphael Isemann         SourceMerger(S.getMerger()) {}
12551e0bbb0SRaphael Isemann 
ImportImpl(Decl * FromD)12651e0bbb0SRaphael Isemann   llvm::Expected<Decl *> ImportImpl(Decl *FromD) override {
12751e0bbb0SRaphael Isemann     if (!TemporarySource || !SourceMerger)
12851e0bbb0SRaphael Isemann       return ASTImporter::ImportImpl(FromD);
12951e0bbb0SRaphael Isemann 
13051e0bbb0SRaphael Isemann     // If we get here, then this source is importing from a temporary ASTContext
13151e0bbb0SRaphael Isemann     // that also has another ExternalASTMerger attached. It could be
13251e0bbb0SRaphael Isemann     // possible that the current ExternalASTMerger and the temporary ASTContext
13351e0bbb0SRaphael Isemann     // share a common ImporterSource, which means that the temporary
13451e0bbb0SRaphael Isemann     // AST could contain declarations that were imported from a source
13551e0bbb0SRaphael Isemann     // that this ExternalASTMerger can access directly. Instead of importing
13651e0bbb0SRaphael Isemann     // such declarations from the temporary ASTContext, they should instead
13751e0bbb0SRaphael Isemann     // be directly imported by this ExternalASTMerger from the original
13851e0bbb0SRaphael Isemann     // source. This way the ExternalASTMerger can safely do a minimal import
13951e0bbb0SRaphael Isemann     // without creating incomplete declarations originated from a temporary
14051e0bbb0SRaphael Isemann     // ASTContext. If we would try to complete such declarations later on, we
14151e0bbb0SRaphael Isemann     // would fail to do so as their temporary AST could be deleted (which means
14251e0bbb0SRaphael Isemann     // that the missing parts of the minimally imported declaration in that
14351e0bbb0SRaphael Isemann     // ASTContext were also deleted).
14451e0bbb0SRaphael Isemann     //
14551e0bbb0SRaphael Isemann     // The following code tracks back any declaration that needs to be
14651e0bbb0SRaphael Isemann     // imported from the temporary ASTContext to a persistent ASTContext.
14751e0bbb0SRaphael Isemann     // Then the ExternalASTMerger tries to import from the persistent
14851e0bbb0SRaphael Isemann     // ASTContext directly by using the associated ASTImporter. If that
14951e0bbb0SRaphael Isemann     // succeeds, this ASTImporter just maps the declarations imported by
15051e0bbb0SRaphael Isemann     // the other (persistent) ASTImporter to this (temporary) ASTImporter.
15151e0bbb0SRaphael Isemann     // The steps can be visualized like this:
15251e0bbb0SRaphael Isemann     //
15351e0bbb0SRaphael Isemann     //  Target AST <--- 3. Indirect import --- Persistent AST
15451e0bbb0SRaphael Isemann     //       ^            of persistent decl        ^
15551e0bbb0SRaphael Isemann     //       |                                      |
15651e0bbb0SRaphael Isemann     // 1. Current import           2. Tracking back to persistent decl
15751e0bbb0SRaphael Isemann     // 4. Map persistent decl                       |
15851e0bbb0SRaphael Isemann     //  & pretend we imported.                      |
15951e0bbb0SRaphael Isemann     //       |                                      |
16051e0bbb0SRaphael Isemann     // Temporary AST -------------------------------'
16151e0bbb0SRaphael Isemann 
16251e0bbb0SRaphael Isemann     // First, ask the ExternalASTMerger of the source where the temporary
16351e0bbb0SRaphael Isemann     // declaration originated from.
16451e0bbb0SRaphael Isemann     Decl *Persistent = SourceMerger->FindOriginalDecl(FromD);
16551e0bbb0SRaphael Isemann     // FromD isn't from a persistent AST, so just do a normal import.
16651e0bbb0SRaphael Isemann     if (!Persistent)
16751e0bbb0SRaphael Isemann       return ASTImporter::ImportImpl(FromD);
16851e0bbb0SRaphael Isemann     // Now ask the current ExternalASTMerger to try import the persistent
16951e0bbb0SRaphael Isemann     // declaration into the target.
17051e0bbb0SRaphael Isemann     ASTContext &PersistentCtx = Persistent->getASTContext();
17151e0bbb0SRaphael Isemann     ASTImporter &OtherImporter = Parent.ImporterForOrigin(PersistentCtx);
17251e0bbb0SRaphael Isemann     // Check that we never end up in the current Importer again.
17351e0bbb0SRaphael Isemann     assert((&PersistentCtx != &getFromContext()) && (&OtherImporter != this) &&
17451e0bbb0SRaphael Isemann            "Delegated to same Importer?");
17551e0bbb0SRaphael Isemann     auto DeclOrErr = OtherImporter.Import(Persistent);
17651e0bbb0SRaphael Isemann     // Errors when importing the persistent decl are treated as if we
17751e0bbb0SRaphael Isemann     // had errors with importing the temporary decl.
17851e0bbb0SRaphael Isemann     if (!DeclOrErr)
17951e0bbb0SRaphael Isemann       return DeclOrErr.takeError();
18051e0bbb0SRaphael Isemann     Decl *D = *DeclOrErr;
18151e0bbb0SRaphael Isemann     // Tell the current ASTImporter that this has already been imported
18251e0bbb0SRaphael Isemann     // to prevent any further queries for the temporary decl.
18351e0bbb0SRaphael Isemann     MapImported(FromD, D);
18451e0bbb0SRaphael Isemann     return D;
18551e0bbb0SRaphael Isemann   }
18651e0bbb0SRaphael Isemann 
18751e0bbb0SRaphael Isemann   /// Implements the ASTImporter interface for tracking back a declaration
18851e0bbb0SRaphael Isemann   /// to its original declaration it came from.
GetOriginalDecl(Decl * To)18951e0bbb0SRaphael Isemann   Decl *GetOriginalDecl(Decl *To) override {
19051e0bbb0SRaphael Isemann     auto It = ToOrigin.find(To);
19151e0bbb0SRaphael Isemann     if (It != ToOrigin.end())
19251e0bbb0SRaphael Isemann       return It->second;
19351e0bbb0SRaphael Isemann     return nullptr;
19451e0bbb0SRaphael Isemann   }
195967d4384SSean Callanan 
196967d4384SSean Callanan   /// Whenever a DeclContext is imported, ensure that ExternalASTSource's origin
197967d4384SSean Callanan   /// map is kept up to date.  Also set the appropriate flags.
Imported(Decl * From,Decl * To)1985e3a7698SRaphael Isemann   void Imported(Decl *From, Decl *To) override {
19951e0bbb0SRaphael Isemann     ToOrigin[To] = From;
20051e0bbb0SRaphael Isemann 
201967d4384SSean Callanan     if (auto *ToDC = dyn_cast<DeclContext>(To)) {
202967d4384SSean Callanan       const bool LoggingEnabled = Parent.LoggingEnabled();
203967d4384SSean Callanan       if (LoggingEnabled)
204967d4384SSean Callanan         logs() << "(ExternalASTMerger*)" << (void*)&Parent
205967d4384SSean Callanan                << " imported (DeclContext*)" << (void*)ToDC
206967d4384SSean Callanan                << ", (ASTContext*)" << (void*)&getToContext()
207967d4384SSean Callanan                << " from (DeclContext*)" << (void*)llvm::cast<DeclContext>(From)
208967d4384SSean Callanan                << ", (ASTContext*)" << (void*)&getFromContext()
209967d4384SSean Callanan                << "\n";
210967d4384SSean Callanan       Source<DeclContext *> FromDC(
211967d4384SSean Callanan           cast<DeclContext>(From)->getPrimaryContext());
212967d4384SSean Callanan       if (FromOrigins.count(FromDC) &&
213967d4384SSean Callanan           Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
214967d4384SSean Callanan         if (LoggingEnabled)
215967d4384SSean Callanan           logs() << "(ExternalASTMerger*)" << (void*)&Parent
216967d4384SSean Callanan                  << " forced origin (DeclContext*)"
217967d4384SSean Callanan                  << (void*)FromOrigins.at(FromDC).DC
218967d4384SSean Callanan                  << ", (ASTContext*)"
219967d4384SSean Callanan                  << (void*)FromOrigins.at(FromDC).AST
220967d4384SSean Callanan                  << "\n";
221967d4384SSean Callanan         Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
222b7160ca4SSean Callanan       } else {
223967d4384SSean Callanan         if (LoggingEnabled)
224967d4384SSean Callanan           logs() << "(ExternalASTMerger*)" << (void*)&Parent
225967d4384SSean Callanan                  << " maybe recording origin (DeclContext*)" << (void*)FromDC
226967d4384SSean Callanan                  << ", (ASTContext*)" << (void*)&getFromContext()
227967d4384SSean Callanan                  << "\n";
228967d4384SSean Callanan         Parent.MaybeRecordOrigin(ToDC, {FromDC, &getFromContext()});
229b7160ca4SSean Callanan       }
230b7160ca4SSean Callanan     }
231967d4384SSean Callanan     if (auto *ToTag = dyn_cast<TagDecl>(To)) {
232967d4384SSean Callanan       ToTag->setHasExternalLexicalStorage();
233ddedf0f9SRaphael Isemann       ToTag->getPrimaryContext()->setMustBuildLookupTable();
234967d4384SSean Callanan       assert(Parent.CanComplete(ToTag));
235967d4384SSean Callanan     } else if (auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
236967d4384SSean Callanan       ToNamespace->setHasExternalVisibleStorage();
237967d4384SSean Callanan       assert(Parent.CanComplete(ToNamespace));
238967d4384SSean Callanan     } else if (auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
239967d4384SSean Callanan       ToContainer->setHasExternalLexicalStorage();
240ddedf0f9SRaphael Isemann       ToContainer->getPrimaryContext()->setMustBuildLookupTable();
241967d4384SSean Callanan       assert(Parent.CanComplete(ToContainer));
242b7160ca4SSean Callanan     }
243b7160ca4SSean Callanan   }
GetReverse()244967d4384SSean Callanan   ASTImporter &GetReverse() { return Reverse; }
245967d4384SSean Callanan };
246b7160ca4SSean Callanan 
HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls,const Candidate & C)247b7160ca4SSean Callanan bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
248967d4384SSean Callanan   if (isa<FunctionDecl>(C.first.get()))
249967d4384SSean Callanan     return false;
2500a0c0332SDavid Blaikie   return llvm::any_of(Decls, [&](const Candidate &D) {
251b7160ca4SSean Callanan     return C.first.get()->getKind() == D.first.get()->getKind();
252b7160ca4SSean Callanan   });
253b7160ca4SSean Callanan }
254967d4384SSean Callanan 
255b7160ca4SSean Callanan } // end namespace
256b7160ca4SSean Callanan 
ImporterForOrigin(ASTContext & OriginContext)257967d4384SSean Callanan ASTImporter &ExternalASTMerger::ImporterForOrigin(ASTContext &OriginContext) {
258967d4384SSean Callanan   for (const std::unique_ptr<ASTImporter> &I : Importers)
259967d4384SSean Callanan     if (&I->getFromContext() == &OriginContext)
260967d4384SSean Callanan       return *I;
261967d4384SSean Callanan   llvm_unreachable("We should have an importer for this origin!");
262967d4384SSean Callanan }
263967d4384SSean Callanan 
264967d4384SSean Callanan namespace {
LazyImporterForOrigin(ExternalASTMerger & Merger,ASTContext & OriginContext)265967d4384SSean Callanan LazyASTImporter &LazyImporterForOrigin(ExternalASTMerger &Merger,
266967d4384SSean Callanan                                    ASTContext &OriginContext) {
267967d4384SSean Callanan   return static_cast<LazyASTImporter &>(
268967d4384SSean Callanan       Merger.ImporterForOrigin(OriginContext));
269967d4384SSean Callanan }
270967d4384SSean Callanan }
271967d4384SSean Callanan 
HasImporterForOrigin(ASTContext & OriginContext)272967d4384SSean Callanan bool ExternalASTMerger::HasImporterForOrigin(ASTContext &OriginContext) {
273967d4384SSean Callanan   for (const std::unique_ptr<ASTImporter> &I : Importers)
274967d4384SSean Callanan     if (&I->getFromContext() == &OriginContext)
275967d4384SSean Callanan       return true;
276967d4384SSean Callanan   return false;
277967d4384SSean Callanan }
278967d4384SSean Callanan 
279967d4384SSean Callanan template <typename CallbackType>
ForEachMatchingDC(const DeclContext * DC,CallbackType Callback)280967d4384SSean Callanan void ExternalASTMerger::ForEachMatchingDC(const DeclContext *DC,
281967d4384SSean Callanan                                           CallbackType Callback) {
282967d4384SSean Callanan   if (Origins.count(DC)) {
283967d4384SSean Callanan     ExternalASTMerger::DCOrigin Origin = Origins[DC];
284967d4384SSean Callanan     LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
285967d4384SSean Callanan     Callback(Importer, Importer.GetReverse(), Origin.DC);
286967d4384SSean Callanan   } else {
287967d4384SSean Callanan     bool DidCallback = false;
288967d4384SSean Callanan     for (const std::unique_ptr<ASTImporter> &Importer : Importers) {
289967d4384SSean Callanan       Source<TranslationUnitDecl *> SourceTU =
290967d4384SSean Callanan           Importer->getFromContext().getTranslationUnitDecl();
291967d4384SSean Callanan       ASTImporter &Reverse =
292967d4384SSean Callanan           static_cast<LazyASTImporter *>(Importer.get())->GetReverse();
293967d4384SSean Callanan       if (auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
294967d4384SSean Callanan         DidCallback = true;
295967d4384SSean Callanan         if (Callback(*Importer, Reverse, SourceDC))
296967d4384SSean Callanan           break;
297967d4384SSean Callanan       }
298967d4384SSean Callanan     }
299967d4384SSean Callanan     if (!DidCallback && LoggingEnabled())
300967d4384SSean Callanan       logs() << "(ExternalASTMerger*)" << (void*)this
3016fc579dfSNico Weber              << " asserting for (DeclContext*)" << (const void*)DC
302967d4384SSean Callanan              << ", (ASTContext*)" << (void*)&Target.AST
303967d4384SSean Callanan              << "\n";
304967d4384SSean Callanan     assert(DidCallback && "Couldn't find a source context matching our DC");
305967d4384SSean Callanan   }
306967d4384SSean Callanan }
307967d4384SSean Callanan 
CompleteType(TagDecl * Tag)308967d4384SSean Callanan void ExternalASTMerger::CompleteType(TagDecl *Tag) {
309967d4384SSean Callanan   assert(Tag->hasExternalLexicalStorage());
310967d4384SSean Callanan   ForEachMatchingDC(Tag, [&](ASTImporter &Forward, ASTImporter &Reverse,
311967d4384SSean Callanan                              Source<const DeclContext *> SourceDC) -> bool {
312967d4384SSean Callanan     auto *SourceTag = const_cast<TagDecl *>(cast<TagDecl>(SourceDC.get()));
313967d4384SSean Callanan     if (SourceTag->hasExternalLexicalStorage())
314967d4384SSean Callanan       SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag);
315967d4384SSean Callanan     if (!SourceTag->getDefinition())
316967d4384SSean Callanan       return false;
31726f72a96SGabor Marton     Forward.MapImported(SourceTag, Tag);
3185ac6d490SGabor Marton     if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
3193b30d658SBalazs Keri       llvm::consumeError(std::move(Err));
320967d4384SSean Callanan     Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
321967d4384SSean Callanan     return true;
322967d4384SSean Callanan   });
323967d4384SSean Callanan }
324967d4384SSean Callanan 
CompleteType(ObjCInterfaceDecl * Interface)325967d4384SSean Callanan void ExternalASTMerger::CompleteType(ObjCInterfaceDecl *Interface) {
326967d4384SSean Callanan   assert(Interface->hasExternalLexicalStorage());
327967d4384SSean Callanan   ForEachMatchingDC(
328967d4384SSean Callanan       Interface, [&](ASTImporter &Forward, ASTImporter &Reverse,
329967d4384SSean Callanan                      Source<const DeclContext *> SourceDC) -> bool {
330967d4384SSean Callanan         auto *SourceInterface = const_cast<ObjCInterfaceDecl *>(
331967d4384SSean Callanan             cast<ObjCInterfaceDecl>(SourceDC.get()));
332967d4384SSean Callanan         if (SourceInterface->hasExternalLexicalStorage())
333967d4384SSean Callanan           SourceInterface->getASTContext().getExternalSource()->CompleteType(
334967d4384SSean Callanan               SourceInterface);
335967d4384SSean Callanan         if (!SourceInterface->getDefinition())
336967d4384SSean Callanan           return false;
33726f72a96SGabor Marton         Forward.MapImported(SourceInterface, Interface);
3385ac6d490SGabor Marton         if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
3393b30d658SBalazs Keri           llvm::consumeError(std::move(Err));
340967d4384SSean Callanan         return true;
341967d4384SSean Callanan       });
342967d4384SSean Callanan }
343967d4384SSean Callanan 
CanComplete(DeclContext * Interface)344967d4384SSean Callanan bool ExternalASTMerger::CanComplete(DeclContext *Interface) {
345967d4384SSean Callanan   assert(Interface->hasExternalLexicalStorage() ||
346967d4384SSean Callanan          Interface->hasExternalVisibleStorage());
347967d4384SSean Callanan   bool FoundMatchingDC = false;
348967d4384SSean Callanan   ForEachMatchingDC(Interface,
349967d4384SSean Callanan                     [&](ASTImporter &Forward, ASTImporter &Reverse,
350967d4384SSean Callanan                         Source<const DeclContext *> SourceDC) -> bool {
351967d4384SSean Callanan                       FoundMatchingDC = true;
352967d4384SSean Callanan                       return true;
353967d4384SSean Callanan                     });
354967d4384SSean Callanan   return FoundMatchingDC;
355967d4384SSean Callanan }
356967d4384SSean Callanan 
357967d4384SSean Callanan namespace {
IsSameDC(const DeclContext * D1,const DeclContext * D2)358967d4384SSean Callanan bool IsSameDC(const DeclContext *D1, const DeclContext *D2) {
359967d4384SSean Callanan   if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
360967d4384SSean Callanan     return true; // There are many cases where Objective-C is ambiguous.
361967d4384SSean Callanan   if (auto *T1 = dyn_cast<TagDecl>(D1))
362967d4384SSean Callanan     if (auto *T2 = dyn_cast<TagDecl>(D2))
363967d4384SSean Callanan       if (T1->getFirstDecl() == T2->getFirstDecl())
364967d4384SSean Callanan         return true;
365967d4384SSean Callanan   return D1 == D2 || D1 == CanonicalizeDC(D2);
366967d4384SSean Callanan }
367967d4384SSean Callanan }
368967d4384SSean Callanan 
MaybeRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)369967d4384SSean Callanan void ExternalASTMerger::MaybeRecordOrigin(const DeclContext *ToDC,
370967d4384SSean Callanan                                           DCOrigin Origin) {
371967d4384SSean Callanan   LazyASTImporter &Importer = LazyImporterForOrigin(*this, *Origin.AST);
372967d4384SSean Callanan   ASTImporter &Reverse = Importer.GetReverse();
373967d4384SSean Callanan   Source<const DeclContext *> FoundFromDC =
374967d4384SSean Callanan       LookupSameContext(Origin.AST->getTranslationUnitDecl(), ToDC, Reverse);
375967d4384SSean Callanan   const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.DC);
376967d4384SSean Callanan   if (DoRecord)
377967d4384SSean Callanan     RecordOriginImpl(ToDC, Origin, Importer);
378967d4384SSean Callanan   if (LoggingEnabled())
379967d4384SSean Callanan     logs() << "(ExternalASTMerger*)" << (void*)this
380967d4384SSean Callanan              << (DoRecord ? " decided " : " decided NOT")
381967d4384SSean Callanan              << " to record origin (DeclContext*)" << (void*)Origin.DC
382967d4384SSean Callanan              << ", (ASTContext*)" << (void*)&Origin.AST
383967d4384SSean Callanan              << "\n";
384967d4384SSean Callanan }
385967d4384SSean Callanan 
ForceRecordOrigin(const DeclContext * ToDC,DCOrigin Origin)386967d4384SSean Callanan void ExternalASTMerger::ForceRecordOrigin(const DeclContext *ToDC,
387967d4384SSean Callanan                                           DCOrigin Origin) {
388967d4384SSean Callanan   RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.AST));
389967d4384SSean Callanan }
390967d4384SSean Callanan 
RecordOriginImpl(const DeclContext * ToDC,DCOrigin Origin,ASTImporter & Importer)391967d4384SSean Callanan void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin,
392967d4384SSean Callanan                                          ASTImporter &Importer) {
393967d4384SSean Callanan   Origins[ToDC] = Origin;
39426f72a96SGabor Marton   Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC)));
395967d4384SSean Callanan }
396967d4384SSean Callanan 
ExternalASTMerger(const ImporterTarget & Target,llvm::ArrayRef<ImporterSource> Sources)397967d4384SSean Callanan ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,
398967d4384SSean Callanan                                      llvm::ArrayRef<ImporterSource> Sources) : LogStream(&llvm::nulls()), Target(Target) {
399e7714fe7SRaphael Isemann   SharedState = std::make_shared<ASTImporterSharedState>(
400e7714fe7SRaphael Isemann       *Target.AST.getTranslationUnitDecl());
401967d4384SSean Callanan   AddSources(Sources);
402967d4384SSean Callanan }
403967d4384SSean Callanan 
FindOriginalDecl(Decl * D)40451e0bbb0SRaphael Isemann Decl *ExternalASTMerger::FindOriginalDecl(Decl *D) {
40551e0bbb0SRaphael Isemann   assert(&D->getASTContext() == &Target.AST);
40651e0bbb0SRaphael Isemann   for (const auto &I : Importers)
40751e0bbb0SRaphael Isemann     if (auto Result = I->GetOriginalDecl(D))
40851e0bbb0SRaphael Isemann       return Result;
40951e0bbb0SRaphael Isemann   return nullptr;
41051e0bbb0SRaphael Isemann }
41151e0bbb0SRaphael Isemann 
AddSources(llvm::ArrayRef<ImporterSource> Sources)412967d4384SSean Callanan void ExternalASTMerger::AddSources(llvm::ArrayRef<ImporterSource> Sources) {
413967d4384SSean Callanan   for (const ImporterSource &S : Sources) {
414cf628714SRaphael Isemann     assert(&S.getASTContext() != &Target.AST);
41551e0bbb0SRaphael Isemann     // Check that the associated merger actually imports into the source AST.
41651e0bbb0SRaphael Isemann     assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.getASTContext());
4172b3d49b6SJonas Devlieghere     Importers.push_back(std::make_unique<LazyASTImporter>(
418cf628714SRaphael Isemann         *this, Target.AST, Target.FM, S, SharedState));
419967d4384SSean Callanan   }
420967d4384SSean Callanan }
421967d4384SSean Callanan 
RemoveSources(llvm::ArrayRef<ImporterSource> Sources)422967d4384SSean Callanan void ExternalASTMerger::RemoveSources(llvm::ArrayRef<ImporterSource> Sources) {
423967d4384SSean Callanan   if (LoggingEnabled())
424967d4384SSean Callanan     for (const ImporterSource &S : Sources)
425967d4384SSean Callanan       logs() << "(ExternalASTMerger*)" << (void *)this
426cf628714SRaphael Isemann              << " removing source (ASTContext*)" << (void *)&S.getASTContext()
427967d4384SSean Callanan              << "\n";
428*d245f2e8SKazu Hirata   llvm::erase_if(Importers,
429967d4384SSean Callanan                  [&Sources](std::unique_ptr<ASTImporter> &Importer) -> bool {
430967d4384SSean Callanan                    for (const ImporterSource &S : Sources) {
431cf628714SRaphael Isemann                      if (&Importer->getFromContext() == &S.getASTContext())
432967d4384SSean Callanan                        return true;
433967d4384SSean Callanan                    }
434967d4384SSean Callanan                    return false;
435*d245f2e8SKazu Hirata                  });
436967d4384SSean Callanan   for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
437967d4384SSean Callanan     std::pair<const DeclContext *, DCOrigin> Origin = *OI;
438967d4384SSean Callanan     bool Erase = false;
439967d4384SSean Callanan     for (const ImporterSource &S : Sources) {
440cf628714SRaphael Isemann       if (&S.getASTContext() == Origin.second.AST) {
441967d4384SSean Callanan         Erase = true;
442967d4384SSean Callanan         break;
443967d4384SSean Callanan       }
444967d4384SSean Callanan     }
445967d4384SSean Callanan     if (Erase)
446967d4384SSean Callanan       OI = Origins.erase(OI);
447967d4384SSean Callanan     else
448967d4384SSean Callanan       ++OI;
449b7160ca4SSean Callanan   }
450b7160ca4SSean Callanan }
451b7160ca4SSean Callanan 
4528fc8510cSAleksei Sidorin template <typename DeclTy>
importSpecializations(DeclTy * D,ASTImporter * Importer)4538fc8510cSAleksei Sidorin static bool importSpecializations(DeclTy *D, ASTImporter *Importer) {
454a1f6b103SBalazs Keri   for (auto *Spec : D->specializations()) {
4555ac6d490SGabor Marton     auto ImportedSpecOrError = Importer->Import(Spec);
456a1f6b103SBalazs Keri     if (!ImportedSpecOrError) {
457a1f6b103SBalazs Keri       llvm::consumeError(ImportedSpecOrError.takeError());
4588fc8510cSAleksei Sidorin       return true;
459a1f6b103SBalazs Keri     }
460a1f6b103SBalazs Keri   }
4618fc8510cSAleksei Sidorin   return false;
4628fc8510cSAleksei Sidorin }
4638fc8510cSAleksei Sidorin 
4648fc8510cSAleksei Sidorin /// Imports specializations from template declarations that can be specialized.
importSpecializationsIfNeeded(Decl * D,ASTImporter * Importer)4658fc8510cSAleksei Sidorin static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer) {
4668fc8510cSAleksei Sidorin   if (!isa<TemplateDecl>(D))
4678fc8510cSAleksei Sidorin     return false;
4688fc8510cSAleksei Sidorin   if (auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
4698fc8510cSAleksei Sidorin     return importSpecializations(FunctionTD, Importer);
4708fc8510cSAleksei Sidorin   else if (auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
4718fc8510cSAleksei Sidorin     return importSpecializations(ClassTD, Importer);
4728fc8510cSAleksei Sidorin   else if (auto *VarTD = dyn_cast<VarTemplateDecl>(D))
4738fc8510cSAleksei Sidorin     return importSpecializations(VarTD, Importer);
4748fc8510cSAleksei Sidorin   return false;
4758fc8510cSAleksei Sidorin }
4768fc8510cSAleksei Sidorin 
FindExternalVisibleDeclsByName(const DeclContext * DC,DeclarationName Name)477b7160ca4SSean Callanan bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
478b7160ca4SSean Callanan                                                        DeclarationName Name) {
479b7160ca4SSean Callanan   llvm::SmallVector<NamedDecl *, 1> Decls;
480967d4384SSean Callanan   llvm::SmallVector<Candidate, 4> Candidates;
481b7160ca4SSean Callanan 
482967d4384SSean Callanan   auto FilterFoundDecl = [&Candidates](const Candidate &C) {
483967d4384SSean Callanan    if (!HasDeclOfSameType(Candidates, C))
484967d4384SSean Callanan      Candidates.push_back(C);
485b7160ca4SSean Callanan   };
486b7160ca4SSean Callanan 
487a1f6b103SBalazs Keri   ForEachMatchingDC(DC,
488a1f6b103SBalazs Keri                     [&](ASTImporter &Forward, ASTImporter &Reverse,
489967d4384SSean Callanan                         Source<const DeclContext *> SourceDC) -> bool {
4905ac6d490SGabor Marton                       auto FromNameOrErr = Reverse.Import(Name);
491a1f6b103SBalazs Keri                       if (!FromNameOrErr) {
492a1f6b103SBalazs Keri                         llvm::consumeError(FromNameOrErr.takeError());
493a1f6b103SBalazs Keri                         return false;
494a1f6b103SBalazs Keri                       }
495a1f6b103SBalazs Keri                       DeclContextLookupResult Result =
496a1f6b103SBalazs Keri                           SourceDC.get()->lookup(*FromNameOrErr);
497b7160ca4SSean Callanan                       for (NamedDecl *FromD : Result) {
498967d4384SSean Callanan                         FilterFoundDecl(std::make_pair(FromD, &Forward));
499b7160ca4SSean Callanan                       }
500967d4384SSean Callanan                       return false;
501b7160ca4SSean Callanan                     });
502b7160ca4SSean Callanan 
503967d4384SSean Callanan   if (Candidates.empty())
504b7160ca4SSean Callanan     return false;
505b7160ca4SSean Callanan 
506967d4384SSean Callanan   Decls.reserve(Candidates.size());
507967d4384SSean Callanan   for (const Candidate &C : Candidates) {
5088fc8510cSAleksei Sidorin     Decl *LookupRes = C.first.get();
5098fc8510cSAleksei Sidorin     ASTImporter *Importer = C.second;
5105ac6d490SGabor Marton     auto NDOrErr = Importer->Import(LookupRes);
5117e6294c0SRaphael Isemann     NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
5128fc8510cSAleksei Sidorin     assert(ND);
5138fc8510cSAleksei Sidorin     // If we don't import specialization, they are not available via lookup
5148fc8510cSAleksei Sidorin     // because the lookup result is imported TemplateDecl and it does not
5158fc8510cSAleksei Sidorin     // reference its specializations until they are imported explicitly.
5168fc8510cSAleksei Sidorin     bool IsSpecImportFailed =
5178fc8510cSAleksei Sidorin         importSpecializationsIfNeeded(LookupRes, Importer);
5188fc8510cSAleksei Sidorin     assert(!IsSpecImportFailed);
519fdc3207dSSam McCall     (void)IsSpecImportFailed;
5208fc8510cSAleksei Sidorin     Decls.push_back(ND);
521b7160ca4SSean Callanan   }
522b7160ca4SSean Callanan   SetExternalVisibleDeclsForName(DC, Name, Decls);
523b7160ca4SSean Callanan   return true;
524b7160ca4SSean Callanan }
525b7160ca4SSean Callanan 
FindExternalLexicalDecls(const DeclContext * DC,llvm::function_ref<bool (Decl::Kind)> IsKindWeWant,SmallVectorImpl<Decl * > & Result)526b7160ca4SSean Callanan void ExternalASTMerger::FindExternalLexicalDecls(
527b7160ca4SSean Callanan     const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
528b7160ca4SSean Callanan     SmallVectorImpl<Decl *> &Result) {
529967d4384SSean Callanan   ForEachMatchingDC(DC, [&](ASTImporter &Forward, ASTImporter &Reverse,
530967d4384SSean Callanan                             Source<const DeclContext *> SourceDC) -> bool {
5314bb0d78cSSean Callanan     for (const Decl *SourceDecl : SourceDC.get()->decls()) {
5324bb0d78cSSean Callanan       if (IsKindWeWant(SourceDecl->getKind())) {
5335ac6d490SGabor Marton         auto ImportedDeclOrErr = Forward.Import(SourceDecl);
534a1f6b103SBalazs Keri         if (ImportedDeclOrErr)
535a1f6b103SBalazs Keri           assert(!(*ImportedDeclOrErr) ||
536a1f6b103SBalazs Keri                  IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
537a1f6b103SBalazs Keri         else
538a1f6b103SBalazs Keri           llvm::consumeError(ImportedDeclOrErr.takeError());
539b7160ca4SSean Callanan       }
540b7160ca4SSean Callanan     }
541967d4384SSean Callanan     return false;
542b7160ca4SSean Callanan   });
543b7160ca4SSean Callanan }
5449092d479SSean Callanan 
545