25template <
typename T>
struct Source {
28 operator T() {
return t; }
29 template <
typename U = T>
U &get() {
return t; }
30 template <
typename U = T>
const U &get()
const {
return t; }
31 template <
typename U>
operator Source<U>() {
return Source<U>(t); }
34typedef std::pair<Source<NamedDecl *>,
ASTImporter *> Candidate;
39 if (isa<LinkageSpecDecl>(DC))
44Source<const DeclContext *>
45LookupSameContext(Source<TranslationUnitDecl *> SourceTU,
const DeclContext *DC,
47 DC = CanonicalizeDC(DC);
51 Source<const DeclContext *> SourceParentDC =
52 LookupSameContext(SourceTU, DC->
getParent(), ReverseImporter);
53 if (!SourceParentDC) {
57 auto *ND = cast<NamedDecl>(DC);
59 auto SourceNameOrErr = ReverseImporter.
Import(Name);
60 if (!SourceNameOrErr) {
61 llvm::consumeError(SourceNameOrErr.takeError());
64 Source<DeclarationName> SourceName = *SourceNameOrErr;
66 SourceParentDC.get()->lookup(SourceName.get());
79 if (isa<DeclContext>(SearchResultDecl) &&
81 return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
105 bool TemporarySource;
108 llvm::DenseMap<Decl *, Decl *> ToOrigin;
111 llvm::raw_ostream &logs() {
return Parent.logs(); }
116 std::shared_ptr<ASTImporterSharedState> SharedState)
117 :
ASTImporter(ToContext, ToFileManager, S.getASTContext(),
121 Reverse(S.getASTContext(), S.getFileManager(), ToContext, ToFileManager,
123 FromOrigins(S.getOriginMap()), TemporarySource(S.isTemporary()),
124 SourceMerger(S.getMerger()) {}
127 if (!TemporarySource || !SourceMerger)
173 assert((&PersistentCtx != &
getFromContext()) && (&OtherImporter !=
this) &&
174 "Delegated to same Importer?");
175 auto DeclOrErr = OtherImporter.
Import(Persistent);
179 return DeclOrErr.takeError();
180 Decl *D = *DeclOrErr;
190 auto It = ToOrigin.find(To);
191 if (It != ToOrigin.end())
201 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
202 const bool LoggingEnabled =
Parent.LoggingEnabled();
204 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
205 <<
" imported (DeclContext*)" << (
void*)ToDC
207 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
210 Source<DeclContext *> FromDC(
211 cast<DeclContext>(From)->getPrimaryContext());
212 if (FromOrigins.count(FromDC) &&
213 Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
215 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
216 <<
" forced origin (DeclContext*)"
217 << (
void*)FromOrigins.at(FromDC).DC
219 << (
void*)FromOrigins.at(FromDC).AST
221 Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
224 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
225 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
231 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
232 ToTag->setHasExternalLexicalStorage();
233 ToTag->getPrimaryContext()->setMustBuildLookupTable();
234 assert(
Parent.CanComplete(ToTag));
235 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
236 ToNamespace->setHasExternalVisibleStorage();
237 assert(
Parent.CanComplete(ToNamespace));
238 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
239 ToContainer->setHasExternalLexicalStorage();
240 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
241 assert(
Parent.CanComplete(ToContainer));
248 if (isa<FunctionDecl>(
C.first.get()))
250 return llvm::any_of(Decls, [&](
const Candidate &D) {
251 return C.first.get()->
getKind() == D.first.get()->getKind();
258 for (
const std::unique_ptr<ASTImporter> &I : Importers)
259 if (&I->getFromContext() == &OriginContext)
261 llvm_unreachable(
"We should have an importer for this origin!");
267 return static_cast<LazyASTImporter &
>(
273 for (
const std::unique_ptr<ASTImporter> &I : Importers)
274 if (&I->getFromContext() == &OriginContext)
279template <
typename CallbackType>
280void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
281 CallbackType Callback) {
282 if (Origins.count(DC)) {
284 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
285 Callback(Importer, Importer.GetReverse(), Origin.
DC);
287 bool DidCallback =
false;
288 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
289 Source<TranslationUnitDecl *> SourceTU =
290 Importer->getFromContext().getTranslationUnitDecl();
292 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
293 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
295 if (Callback(*Importer, Reverse, SourceDC))
300 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
301 <<
" asserting for (DeclContext*)" << (
const void*)DC
302 <<
", (ASTContext*)" << (
void*)&Target.
AST
304 assert(DidCallback &&
"Couldn't find a source context matching our DC");
311 Source<const DeclContext *> SourceDC) ->
bool {
312 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
313 if (SourceTag->hasExternalLexicalStorage())
315 if (!SourceTag->getDefinition())
319 llvm::consumeError(std::move(Err));
329 Source<const DeclContext *> SourceDC) ->
bool {
331 cast<ObjCInterfaceDecl>(SourceDC.get()));
332 if (SourceInterface->hasExternalLexicalStorage())
335 if (!SourceInterface->getDefinition())
339 llvm::consumeError(std::move(Err));
347 bool FoundMatchingDC =
false;
348 ForEachMatchingDC(Interface,
350 Source<const DeclContext *> SourceDC) ->
bool {
351 FoundMatchingDC =
true;
354 return FoundMatchingDC;
359 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
361 if (
auto *T1 = dyn_cast<TagDecl>(D1))
362 if (
auto *T2 = dyn_cast<TagDecl>(D2))
363 if (T1->getFirstDecl() == T2->getFirstDecl())
365 return D1 == D2 || D1 == CanonicalizeDC(D2);
371 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
373 Source<const DeclContext *> FoundFromDC =
375 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
377 RecordOriginImpl(ToDC, Origin, Importer);
379 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
380 << (DoRecord ?
" decided " :
" decided NOT")
381 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC
382 <<
", (ASTContext*)" << (
void*)&Origin.
AST
391void ExternalASTMerger::RecordOriginImpl(
const DeclContext *ToDC, DCOrigin Origin,
393 Origins[ToDC] = Origin;
394 Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC),
const_cast<Decl*
>(cast<Decl>(ToDC)));
399 SharedState = std::make_shared<ASTImporterSharedState>(
400 *
Target.AST.getTranslationUnitDecl());
406 for (
const auto &I : Importers)
407 if (
auto Result = I->GetOriginalDecl(D))
416 assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.
getASTContext());
417 Importers.push_back(std::make_unique<LazyASTImporter>(
418 *
this, Target.
AST, Target.
FM, S, SharedState));
425 logs() <<
"(ExternalASTMerger*)" << (
void *)
this
426 <<
" removing source (ASTContext*)" << (
void *)&S.
getASTContext()
428 llvm::erase_if(Importers,
429 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
436 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
437 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
446 OI = Origins.erase(OI);
452template <
typename DeclTy>
454 for (
auto *Spec : D->specializations()) {
455 auto ImportedSpecOrError = Importer->
Import(Spec);
456 if (!ImportedSpecOrError) {
457 llvm::consumeError(ImportedSpecOrError.takeError());
466 if (!isa<TemplateDecl>(D))
468 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
470 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
472 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
482 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
483 if (!HasDeclOfSameType(Candidates,
C))
484 Candidates.push_back(
C);
487 ForEachMatchingDC(DC,
489 Source<const DeclContext *> SourceDC) ->
bool {
490 auto FromNameOrErr = Reverse.
Import(Name);
491 if (!FromNameOrErr) {
492 llvm::consumeError(FromNameOrErr.takeError());
496 SourceDC.get()->lookup(*FromNameOrErr);
498 FilterFoundDecl(std::make_pair(FromD, &Forward));
503 if (Candidates.empty())
506 Decls.reserve(Candidates.size());
507 for (
const Candidate &
C : Candidates) {
508 Decl *LookupRes =
C.first.get();
510 auto NDOrErr = Importer->
Import(LookupRes);
511 NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
516 bool IsSpecImportFailed =
518 assert(!IsSpecImportFailed);
519 (void)IsSpecImportFailed;
530 Source<const DeclContext *> SourceDC) ->
bool {
531 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
532 if (IsKindWeWant(SourceDecl->getKind())) {
533 auto ImportedDeclOrErr = Forward.Import(SourceDecl);
534 if (ImportedDeclOrErr)
535 assert(!(*ImportedDeclOrErr) ||
536 IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
538 llvm::consumeError(ImportedDeclOrErr.takeError());
Defines the clang::ASTContext interface.
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
static bool importSpecializations(DeclTy *D, ASTImporter *Importer)
static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer)
Imports specializations from template declarations that can be specialized.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
ExternalASTSource * getExternalSource() const
Retrieve a pointer to the external AST source associated with this AST context, if any.
Imports selected nodes from one AST context into another context, merging AST nodes where appropriate...
ASTContext & getFromContext() const
Retrieve the context that AST nodes are being imported from.
ASTContext & getToContext() const
Retrieve the context that AST nodes are being imported into.
Decl * MapImported(Decl *From, Decl *To)
Store and assign the imported declaration to its counterpart.
llvm::Error ImportDefinition(Decl *From)
Import the definition of the given declaration, including all of the declarations it contains.
virtual Decl * GetOriginalDecl(Decl *To)
Called by StructuralEquivalenceContext.
virtual void Imported(Decl *From, Decl *To)
Subclasses can override this function to observe all of the From -> To declaration mappings as they a...
virtual Expected< Decl * > ImportImpl(Decl *From)
Can be overwritten by subclasses to implement their own import logic.
llvm::Expected< ExprWithCleanups::CleanupObject > Import(ExprWithCleanups::CleanupObject From)
Import cleanup objects owned by ExprWithCleanup.
The results of name lookup within a DeclContext.
bool isSingleResult() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool hasExternalVisibleStorage() const
Whether this DeclContext has external storage containing additional declarations that are visible in ...
bool isTranslationUnit() const
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
Decl::Kind getDeclKind() const
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
Kind
Lists the kind of concrete classes of Decl.
The name of a declaration.
A source for an ExternalASTMerger.
ExternalASTSource implementation that merges information from several ASTContexts.
llvm::raw_ostream & logs()
Log something if there is a logging callback installed.
void AddSources(llvm::ArrayRef< ImporterSource > Sources)
Add a set of ASTContexts as possible origins.
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override
Implementation of the ExternalASTSource API.
ASTImporter & ImporterForOrigin(ASTContext &OriginContext)
Returns a reference to the ASTImporter from Importers whose origin is OriginContext.
Decl * FindOriginalDecl(Decl *D)
Asks all connected ASTImporters if any of them imported the given declaration.
void CompleteType(TagDecl *Tag) override
Implementation of the ExternalASTSource API.
void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin)
Records an origin in Origins only if name lookup would find something different or nothing at all.
void RemoveSources(llvm::ArrayRef< ImporterSource > Sources)
Remove a set of ASTContexts as possible origins.
std::map< const DeclContext *, DCOrigin > OriginMap
void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin)
Regardless of any checks, override the Origin for a DeclContext.
ExternalASTMerger(const ImporterTarget &Target, llvm::ArrayRef< ImporterSource > Sources)
bool CanComplete(DeclContext *DC)
Returns true if DC can be found in any source AST context.
bool LoggingEnabled()
True if the log stream is not llvm::nulls();.
bool HasImporterForOrigin(ASTContext &OriginContext)
Returns true if Importers contains an ASTImporter whose source is OriginContext.
void FindExternalLexicalDecls(const DeclContext *DC, llvm::function_ref< bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl< Decl * > &Result) override
Implementation of the ExternalASTSource API.
static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef< NamedDecl * > Decls)
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
Implements support for file system lookup, file system caching, and directory search management.
This represents a decl that may have a name.
Represents an ObjC class declaration.
ASTContext & getASTContext() const
Represents the declaration of a struct/union/class/enum.
void setCompleteDefinition(bool V=true)
True if this decl has its body fully specified.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
YAML serialization mapping.
A single origin for a DeclContext.
The target for an ExternalASTMerger.