21 using namespace clang;
25 template <
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); }
34 typedef std::pair<Source<NamedDecl *>,
ASTImporter *> Candidate;
39 if (isa<LinkageSpecDecl>(DC))
44 Source<const DeclContext *>
45 LookupSameContext(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());
67 size_t SearchResultSize = SearchResult.
size();
68 if (SearchResultSize == 0 || SearchResultSize > 1) {
80 NamedDecl *SearchResultDecl = SearchResult[0];
81 if (isa<DeclContext>(SearchResultDecl) &&
83 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)
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;
183 MapImported(FromD, D);
189 Decl *GetOriginalDecl(
Decl *To)
override {
190 auto It = ToOrigin.find(To);
191 if (It != ToOrigin.end())
198 void Imported(
Decl *From,
Decl *To)
override {
201 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
204 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
205 <<
" imported (DeclContext*)" << (
void*)ToDC
206 <<
", (ASTContext*)" << (
void*)&getToContext()
207 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
208 <<
", (ASTContext*)" << (
void*)&getFromContext()
210 Source<DeclContext *> FromDC(
212 if (FromOrigins.count(FromDC) &&
215 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
216 <<
" forced origin (DeclContext*)" 217 << (
void*)FromOrigins.at(FromDC).DC
219 << (
void*)FromOrigins.at(FromDC).AST
224 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
225 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
226 <<
", (ASTContext*)" << (
void*)&getFromContext()
231 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
232 ToTag->setHasExternalLexicalStorage();
233 ToTag->getPrimaryContext()->setMustBuildLookupTable();
235 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
236 ToNamespace->setHasExternalVisibleStorage();
238 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
239 ToContainer->setHasExternalLexicalStorage();
240 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
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)
279 template <
typename CallbackType>
280 void 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))
299 if (!DidCallback && LoggingEnabled())
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);
378 if (LoggingEnabled())
379 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 380 << (DoRecord ?
" decided " :
" decided NOT")
381 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC 382 <<
", (ASTContext*)" << (
void*)&Origin.
AST 388 RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.
AST));
393 Origins[ToDC] = Origin;
394 Importer.ASTImporter::MapImported(cast<Decl>(Origin.
DC), const_cast<Decl*>(cast<Decl>(ToDC)));
399 SharedState = std::make_shared<ASTImporterSharedState>(
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()
429 std::remove_if(Importers.begin(), Importers.end(),
430 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
438 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
439 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
448 OI = Origins.erase(OI);
454 template <
typename DeclTy>
456 for (
auto *Spec : D->specializations()) {
457 auto ImportedSpecOrError = Importer->
Import(Spec);
458 if (!ImportedSpecOrError) {
459 llvm::consumeError(ImportedSpecOrError.takeError());
468 if (!isa<TemplateDecl>(D))
470 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
472 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
474 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
484 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
485 if (!HasDeclOfSameType(Candidates, C))
486 Candidates.push_back(C);
489 ForEachMatchingDC(DC,
491 Source<const DeclContext *> SourceDC) ->
bool {
492 auto FromNameOrErr = Reverse.
Import(Name);
493 if (!FromNameOrErr) {
494 llvm::consumeError(FromNameOrErr.takeError());
498 SourceDC.get()->lookup(*FromNameOrErr);
500 FilterFoundDecl(std::make_pair(FromD, &Forward));
505 if (Candidates.empty())
508 Decls.reserve(Candidates.size());
509 for (
const Candidate &C : Candidates) {
510 Decl *LookupRes = C.first.get();
512 auto NDOrErr = Importer->
Import(LookupRes);
513 NamedDecl *ND = cast<NamedDecl>(llvm::cantFail(std::move(NDOrErr)));
518 bool IsSpecImportFailed =
520 assert(!IsSpecImportFailed);
521 (void)IsSpecImportFailed;
532 Source<const DeclContext *> SourceDC) ->
bool {
533 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
534 if (IsKindWeWant(SourceDecl->getKind())) {
535 auto ImportedDeclOrErr = Forward.
Import(SourceDecl);
536 if (ImportedDeclOrErr)
537 assert(!(*ImportedDeclOrErr) ||
538 IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
540 llvm::consumeError(ImportedDeclOrErr.takeError());
virtual Expected< Decl * > ImportImpl(Decl *From)
Can be overwritten by subclasses to implement their own import logic.
Defines the clang::ASTContext interface.
void MaybeRecordOrigin(const DeclContext *ToDC, DCOrigin Origin)
Records an origin in Origins only if name lookup would find something different or nothing at all...
unsigned llvm::PointerUnion< const Decl *, const Expr * > DeclTy
void setCompleteDefinition(bool V=true)
True if this decl has its body fully specified.
Implements support for file system lookup, file system caching, and directory search management...
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
Decl - This represents one declaration (or definition), e.g.
Defines the C++ template declaration subclasses.
bool HasImporterForOrigin(ASTContext &OriginContext)
Returns true if Importers contains an ASTImporter whose source is OriginContext.
bool hasExternalVisibleStorage() const
Whether this DeclContext has external storage containing additional declarations that are visible in ...
static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef< NamedDecl *> Decls)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
The results of name lookup within a DeclContext.
void AddSources(llvm::ArrayRef< ImporterSource > Sources)
Add a set of ASTContexts as possible origins.
LLVM_NODISCARD llvm::Error ImportDefinition(Decl *From)
Import the definition of the given declaration, including all of the declarations it contains...
The target for an ExternalASTMerger.
Represents an ObjC class declaration.
bool LoggingEnabled()
True if the log stream is not llvm::nulls();.
Decl * MapImported(Decl *From, Decl *To)
Store and assign the imported declaration to its counterpart.
A single origin for a DeclContext.
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override
Implementation of the ExternalASTSource API.
DeclContext * getParent()
getParent - Returns the containing DeclContext.
The result type of a method or function.
Decl::Kind getDeclKind() const
ASTContext & getASTContext() const
ASTImporter & ImporterForOrigin(ASTContext &OriginContext)
Returns a reference to the ASTImporter from Importers whose origin is OriginContext.
Represents the declaration of a struct/union/class/enum.
ASTContext & getASTContext() const LLVM_READONLY
llvm::Expected< QualType > Import(QualType FromT)
Import the given type from the "from" context into the "to" context.
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
std::map< const DeclContext *, DCOrigin > OriginMap
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool CanComplete(DeclContext *DC)
Returns true if DC can be found in any source AST context.
static bool importSpecializations(DeclTy *D, ASTImporter *Importer)
The name of a declaration.
void RemoveSources(llvm::ArrayRef< ImporterSource > Sources)
Remove a set of ASTContexts as possible origins.
llvm::raw_ostream & logs()
Log something if there is a logging callback installed.
A source for an ExternalASTMerger.
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...
virtual void CompleteType(TagDecl *Tag)
Gives the external AST source an opportunity to complete an incomplete type.
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
void FindExternalLexicalDecls(const DeclContext *DC, llvm::function_ref< bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl< Decl *> &Result) override
Implementation of the ExternalASTSource API.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
TranslationUnitDecl * getTranslationUnitDecl() const
void CompleteType(TagDecl *Tag) override
Implementation of the ExternalASTSource API.
ASTContext & getFromContext() const
Retrieve the context that AST nodes are being imported from.
void ForceRecordOrigin(const DeclContext *ToDC, DCOrigin Origin)
Regardless of any checks, override the Origin for a DeclContext.
static bool importSpecializationsIfNeeded(Decl *D, ASTImporter *Importer)
Imports specializations from template declarations that can be specialized.
Kind
Lists the kind of concrete classes of Decl.
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
Decl * FindOriginalDecl(Decl *D)
Asks all connected ASTImporters if any of them imported the given declaration.
This represents a decl that may have a name.
bool isTranslationUnit() const
ExternalASTSource implementation that merges information from several ASTContexts.
ExternalASTMerger(const ImporterTarget &Target, llvm::ArrayRef< ImporterSource > Sources)