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 return ToOrigin.lookup(To);
198 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
199 const bool LoggingEnabled =
Parent.LoggingEnabled();
201 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
202 <<
" imported (DeclContext*)" << (
void*)ToDC
204 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
207 Source<DeclContext *> FromDC(
208 cast<DeclContext>(From)->getPrimaryContext());
209 if (FromOrigins.count(FromDC) &&
210 Parent.HasImporterForOrigin(*FromOrigins.at(FromDC).AST)) {
212 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
213 <<
" forced origin (DeclContext*)"
214 << (
void*)FromOrigins.at(FromDC).DC
216 << (
void*)FromOrigins.at(FromDC).AST
218 Parent.ForceRecordOrigin(ToDC, FromOrigins.at(FromDC));
221 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
222 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
228 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
229 ToTag->setHasExternalLexicalStorage();
230 ToTag->getPrimaryContext()->setMustBuildLookupTable();
231 assert(
Parent.CanComplete(ToTag));
232 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
233 ToNamespace->setHasExternalVisibleStorage();
234 assert(
Parent.CanComplete(ToNamespace));
235 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
236 ToContainer->setHasExternalLexicalStorage();
237 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
238 assert(
Parent.CanComplete(ToContainer));
245 if (isa<FunctionDecl>(
C.first.get()))
247 return llvm::any_of(Decls, [&](
const Candidate &D) {
248 return C.first.get()->
getKind() == D.first.get()->getKind();
255 for (
const std::unique_ptr<ASTImporter> &I : Importers)
256 if (&I->getFromContext() == &OriginContext)
258 llvm_unreachable(
"We should have an importer for this origin!");
264 return static_cast<LazyASTImporter &
>(
270 for (
const std::unique_ptr<ASTImporter> &I : Importers)
271 if (&I->getFromContext() == &OriginContext)
276template <
typename CallbackType>
277void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
278 CallbackType Callback) {
279 if (Origins.count(DC)) {
281 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
282 Callback(Importer, Importer.GetReverse(), Origin.
DC);
284 bool DidCallback =
false;
285 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
286 Source<TranslationUnitDecl *> SourceTU =
287 Importer->getFromContext().getTranslationUnitDecl();
289 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
290 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
292 if (Callback(*Importer, Reverse, SourceDC))
297 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
298 <<
" asserting for (DeclContext*)" << (
const void*)DC
299 <<
", (ASTContext*)" << (
void*)&
Target.AST
301 assert(DidCallback &&
"Couldn't find a source context matching our DC");
308 Source<const DeclContext *> SourceDC) ->
bool {
309 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
310 if (SourceTag->hasExternalLexicalStorage())
312 if (!SourceTag->getDefinition())
316 llvm::consumeError(std::move(Err));
323 assert(
Interface->hasExternalLexicalStorage());
326 Source<const DeclContext *> SourceDC) ->
bool {
328 cast<ObjCInterfaceDecl>(SourceDC.get()));
329 if (SourceInterface->hasExternalLexicalStorage())
332 if (!SourceInterface->getDefinition())
336 llvm::consumeError(std::move(Err));
342 assert(
Interface->hasExternalLexicalStorage() ||
344 bool FoundMatchingDC =
false;
347 Source<const DeclContext *> SourceDC) ->
bool {
348 FoundMatchingDC =
true;
351 return FoundMatchingDC;
356 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
358 if (
auto *T1 = dyn_cast<TagDecl>(D1))
359 if (
auto *T2 = dyn_cast<TagDecl>(D2))
360 if (T1->getFirstDecl() == T2->getFirstDecl())
362 return D1 == D2 || D1 == CanonicalizeDC(D2);
368 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
370 Source<const DeclContext *> FoundFromDC =
372 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
374 RecordOriginImpl(ToDC, Origin, Importer);
376 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
377 << (DoRecord ?
" decided " :
" decided NOT")
378 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC
379 <<
", (ASTContext*)" << (
void*)&Origin.
AST
388void ExternalASTMerger::RecordOriginImpl(
const DeclContext *ToDC, DCOrigin Origin,
390 Origins[ToDC] = Origin;
391 Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC),
const_cast<Decl*
>(cast<Decl>(ToDC)));
396 SharedState = std::make_shared<ASTImporterSharedState>(
397 *
Target.AST.getTranslationUnitDecl());
403 for (
const auto &I : Importers)
404 if (
auto Result = I->GetOriginalDecl(D))
413 assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.
getASTContext());
414 Importers.push_back(std::make_unique<LazyASTImporter>(
422 logs() <<
"(ExternalASTMerger*)" << (
void *)
this
423 <<
" removing source (ASTContext*)" << (
void *)&S.
getASTContext()
425 llvm::erase_if(Importers,
426 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
433 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
434 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
443 OI = Origins.erase(OI);
449template <
typename DeclTy>
451 for (
auto *Spec : D->specializations()) {
452 auto ImportedSpecOrError = Importer->
Import(Spec);
453 if (!ImportedSpecOrError) {
454 llvm::consumeError(ImportedSpecOrError.takeError());
463 if (!isa<TemplateDecl>(D))
465 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
467 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
469 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
479 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
480 if (!HasDeclOfSameType(Candidates,
C))
481 Candidates.push_back(
C);
484 ForEachMatchingDC(DC,
486 Source<const DeclContext *> SourceDC) ->
bool {
487 auto FromNameOrErr = Reverse.
Import(Name);
488 if (!FromNameOrErr) {
489 llvm::consumeError(FromNameOrErr.takeError());
493 SourceDC.get()->lookup(*FromNameOrErr);
495 FilterFoundDecl(std::make_pair(FromD, &Forward));
500 if (Candidates.empty())
503 Decls.reserve(Candidates.size());
504 for (
const Candidate &
C : Candidates) {
505 Decl *LookupRes =
C.first.get();
507 auto NDOrErr = Importer->
Import(LookupRes);
508 NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
513 bool IsSpecImportFailed =
515 assert(!IsSpecImportFailed);
516 (void)IsSpecImportFailed;
527 Source<const DeclContext *> SourceDC) ->
bool {
528 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
529 if (IsKindWeWant(SourceDecl->getKind())) {
530 auto ImportedDeclOrErr = Forward.Import(SourceDecl);
531 if (ImportedDeclOrErr)
532 assert(!(*ImportedDeclOrErr) ||
533 IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
535 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.
llvm::MachO::Target Target
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 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.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
Diagnostic wrappers for TextAPI types for error reporting.
A single origin for a DeclContext.
The target for an ExternalASTMerger.