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 (
auto It = FromOrigins.find(FromDC);
210 It != FromOrigins.end() &&
211 Parent.HasImporterForOrigin(*It->second.AST)) {
213 logs() <<
"(ExternalASTMerger*)" << (
void *)&Parent
214 <<
" forced origin (DeclContext*)" << (
void *)It->second.DC
215 <<
", (ASTContext*)" << (
void *)It->second.AST <<
"\n";
216 Parent.ForceRecordOrigin(ToDC, It->second);
219 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
220 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
226 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
227 ToTag->setHasExternalLexicalStorage();
228 ToTag->getPrimaryContext()->setMustBuildLookupTable();
229 assert(
Parent.CanComplete(ToTag));
230 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
231 ToNamespace->setHasExternalVisibleStorage();
232 assert(
Parent.CanComplete(ToNamespace));
233 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
234 ToContainer->setHasExternalLexicalStorage();
235 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
236 assert(
Parent.CanComplete(ToContainer));
243 if (isa<FunctionDecl>(
C.first.get()))
245 return llvm::any_of(Decls, [&](
const Candidate &
D) {
253 for (
const std::unique_ptr<ASTImporter> &I : Importers)
254 if (&I->getFromContext() == &OriginContext)
256 llvm_unreachable(
"We should have an importer for this origin!");
262 return static_cast<LazyASTImporter &
>(
268 for (
const std::unique_ptr<ASTImporter> &I : Importers)
269 if (&I->getFromContext() == &OriginContext)
274template <
typename CallbackType>
275void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
276 CallbackType Callback) {
277 if (
auto It = Origins.find(DC); It != Origins.end()) {
279 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
280 Callback(Importer, Importer.GetReverse(), Origin.
DC);
282 bool DidCallback =
false;
283 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
284 Source<TranslationUnitDecl *> SourceTU =
285 Importer->getFromContext().getTranslationUnitDecl();
287 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
288 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
290 if (Callback(*Importer, Reverse, SourceDC))
295 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
296 <<
" asserting for (DeclContext*)" << (
const void*)DC
297 <<
", (ASTContext*)" << (
void*)&
Target.AST
299 assert(DidCallback &&
"Couldn't find a source context matching our DC");
304 assert(Tag->hasExternalLexicalStorage());
306 Source<const DeclContext *> SourceDC) ->
bool {
307 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
308 if (SourceTag->hasExternalLexicalStorage())
310 if (!SourceTag->getDefinition())
312 Forward.MapImported(SourceTag, Tag);
313 if (llvm::Error Err = Forward.ImportDefinition(SourceTag))
314 llvm::consumeError(std::move(Err));
315 Tag->setCompleteDefinition(SourceTag->isCompleteDefinition());
321 assert(
Interface->hasExternalLexicalStorage());
324 Source<const DeclContext *> SourceDC) ->
bool {
326 cast<ObjCInterfaceDecl>(SourceDC.get()));
327 if (SourceInterface->hasExternalLexicalStorage())
330 if (!SourceInterface->getDefinition())
332 Forward.MapImported(SourceInterface,
Interface);
333 if (llvm::Error Err = Forward.ImportDefinition(SourceInterface))
334 llvm::consumeError(std::move(Err));
340 assert(
Interface->hasExternalLexicalStorage() ||
342 bool FoundMatchingDC =
false;
345 Source<const DeclContext *> SourceDC) ->
bool {
346 FoundMatchingDC =
true;
349 return FoundMatchingDC;
354 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
356 if (
auto *T1 = dyn_cast<TagDecl>(D1))
357 if (
auto *T2 = dyn_cast<TagDecl>(D2))
358 if (T1->getFirstDecl() == T2->getFirstDecl())
360 return D1 == D2 || D1 == CanonicalizeDC(D2);
366 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
368 Source<const DeclContext *> FoundFromDC =
370 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
372 RecordOriginImpl(ToDC, Origin, Importer);
374 logs() <<
"(ExternalASTMerger*)" << (
void*)
this
375 << (DoRecord ?
" decided " :
" decided NOT")
376 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC
377 <<
", (ASTContext*)" << (
void*)&Origin.
AST
386void ExternalASTMerger::RecordOriginImpl(
const DeclContext *ToDC, DCOrigin Origin,
388 Origins[ToDC] = Origin;
389 Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC),
const_cast<Decl*
>(cast<Decl>(ToDC)));
395 SharedState = std::make_shared<ASTImporterSharedState>(
396 *
Target.AST.getTranslationUnitDecl());
402 for (
const auto &I : Importers)
403 if (
auto Result = I->GetOriginalDecl(
D))
412 assert(!S.getMerger() || &S.getMerger()->Target.AST == &S.
getASTContext());
413 Importers.push_back(std::make_unique<LazyASTImporter>(
421 logs() <<
"(ExternalASTMerger*)" << (
void *)
this
422 <<
" removing source (ASTContext*)" << (
void *)&S.
getASTContext()
424 llvm::erase_if(Importers,
425 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
432 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
433 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
442 OI = Origins.erase(OI);
448template <
typename DeclTy>
450 for (
auto *Spec :
D->specializations()) {
451 auto ImportedSpecOrError = Importer->
Import(Spec);
452 if (!ImportedSpecOrError) {
453 llvm::consumeError(ImportedSpecOrError.takeError());
462 if (!isa<TemplateDecl>(
D))
464 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(
D))
466 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(
D))
468 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.
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.
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.
std::map< const DeclContext *, DCOrigin > OriginMap
ExternalASTMerger(const ImporterTarget &Target, ArrayRef< ImporterSource > Sources)
void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin)
Regardless of any checks, override the Origin for a DeclContext.
void RemoveSources(ArrayRef< ImporterSource > Sources)
Remove a set of ASTContexts as possible origins.
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name, const DeclContext *OriginalDC) override
Implementation of the ExternalASTSource API.
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();.
void AddSources(ArrayRef< ImporterSource > Sources)
Add a set of ASTContexts as possible origins.
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.