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) {
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");
306 assert(Tag->hasExternalLexicalStorage());
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));
317 Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
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 ...
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.
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.