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