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