22 using namespace clang;
26 template <
typename T>
struct Source {
29 operator T() {
return t; }
30 template <
typename U = T> U &
get() {
return t; }
31 template <
typename U = T>
const U &
get()
const {
return t; }
32 template <
typename U>
operator Source<U>() {
return Source<U>(t); }
35 typedef std::pair<Source<NamedDecl *>,
ASTImporter *> Candidate;
40 if (isa<LinkageSpecDecl>(DC))
45 Source<const DeclContext *>
46 LookupSameContext(Source<TranslationUnitDecl *> SourceTU,
const DeclContext *DC,
48 DC = CanonicalizeDC(DC);
52 Source<const DeclContext *> SourceParentDC =
53 LookupSameContext(SourceTU, DC->
getParent(), ReverseImporter);
54 if (!SourceParentDC) {
58 auto *ND = cast<NamedDecl>(DC);
60 Source<DeclarationName> SourceName = ReverseImporter.
Import(Name);
62 SourceParentDC.get()->lookup(SourceName.get());
63 size_t SearchResultSize = SearchResult.
size();
64 if (SearchResultSize == 0 || SearchResultSize > 1) {
76 NamedDecl *SearchResultDecl = SearchResult[0];
77 if (isa<DeclContext>(SearchResultDecl) &&
79 return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
101 llvm::raw_ostream &logs() {
return Parent.
logs(); }
107 :
ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
109 Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
110 ToFileManager,
true), FromOrigins(_FromOrigins) {}
115 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
118 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
119 <<
" imported (DeclContext*)" << (
void*)ToDC
120 <<
", (ASTContext*)" << (
void*)&getToContext()
121 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
122 <<
", (ASTContext*)" << (
void*)&getFromContext()
124 Source<DeclContext *> FromDC(
126 if (FromOrigins.count(FromDC) &&
129 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
130 <<
" forced origin (DeclContext*)" 131 << (
void*)FromOrigins.at(FromDC).DC
133 << (
void*)FromOrigins.at(FromDC).AST
138 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
139 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
140 <<
", (ASTContext*)" << (
void*)&getFromContext()
145 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
146 ToTag->setHasExternalLexicalStorage();
147 ToTag->getPrimaryContext()->setMustBuildLookupTable();
149 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
150 ToNamespace->setHasExternalVisibleStorage();
152 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
153 ToContainer->setHasExternalLexicalStorage();
154 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
163 if (isa<FunctionDecl>(C.first.get()))
165 return llvm::any_of(Decls, [&](
const Candidate &D) {
166 return C.first.get()->getKind() == D.first.get()->getKind();
173 for (
const std::unique_ptr<ASTImporter> &I : Importers)
174 if (&I->getFromContext() == &OriginContext)
176 llvm_unreachable(
"We should have an importer for this origin!");
182 return static_cast<LazyASTImporter &
>(
188 for (
const std::unique_ptr<ASTImporter> &I : Importers)
189 if (&I->getFromContext() == &OriginContext)
194 template <
typename CallbackType>
195 void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
196 CallbackType Callback) {
197 if (Origins.count(DC)) {
199 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
200 Callback(Importer, Importer.GetReverse(), Origin.
DC);
202 bool DidCallback =
false;
203 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
204 Source<TranslationUnitDecl *> SourceTU =
205 Importer->getFromContext().getTranslationUnitDecl();
207 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
208 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
210 if (Callback(*Importer, Reverse, SourceDC))
214 if (!DidCallback && LoggingEnabled())
215 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 216 <<
" asserting for (DeclContext*)" << (
const void*)DC
217 <<
", (ASTContext*)" << (
void*)&
Target.AST
219 assert(DidCallback &&
"Couldn't find a source context matching our DC");
226 Source<const DeclContext *> SourceDC) ->
bool {
227 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
228 if (SourceTag->hasExternalLexicalStorage())
230 if (!SourceTag->getDefinition())
234 llvm::consumeError(std::move(Err));
244 Source<const DeclContext *> SourceDC) ->
bool {
246 cast<ObjCInterfaceDecl>(SourceDC.get()));
247 if (SourceInterface->hasExternalLexicalStorage())
250 if (!SourceInterface->getDefinition())
254 llvm::consumeError(std::move(Err));
262 bool FoundMatchingDC =
false;
263 ForEachMatchingDC(Interface,
265 Source<const DeclContext *> SourceDC) ->
bool {
266 FoundMatchingDC =
true;
269 return FoundMatchingDC;
274 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
276 if (
auto *T1 = dyn_cast<TagDecl>(D1))
277 if (
auto *T2 = dyn_cast<TagDecl>(D2))
278 if (T1->getFirstDecl() == T2->getFirstDecl())
280 return D1 == D2 || D1 == CanonicalizeDC(D2);
286 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
288 Source<const DeclContext *> FoundFromDC =
290 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
292 RecordOriginImpl(ToDC, Origin, Importer);
293 if (LoggingEnabled())
294 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 295 << (DoRecord ?
" decided " :
" decided NOT")
296 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC 297 <<
", (ASTContext*)" << (
void*)&Origin.
AST 303 RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.
AST));
308 Origins[ToDC] = Origin;
309 Importer.ASTImporter::MapImported(cast<Decl>(Origin.
DC), const_cast<Decl*>(cast<Decl>(ToDC)));
319 assert(&S.AST != &Target.
AST);
320 Importers.push_back(llvm::make_unique<LazyASTImporter>(
321 *
this, Target.
AST, Target.
FM, S.AST, S.FM, S.OM));
328 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 329 <<
" removing source (ASTContext*)" << (
void*)&S.AST
332 std::remove_if(Importers.begin(), Importers.end(),
333 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
341 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
342 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
345 if (&S.AST == Origin.second.AST) {
351 OI = Origins.erase(OI);
357 template <
typename DeclTy>
359 for (
auto *Spec : D->specializations())
360 if (!Importer->
Import(Spec))
367 if (!isa<TemplateDecl>(D))
369 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
371 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
373 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
383 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
384 if (!HasDeclOfSameType(Candidates, C))
385 Candidates.push_back(C);
389 Source<const DeclContext *> SourceDC) ->
bool {
393 FilterFoundDecl(std::make_pair(FromD, &Forward));
398 if (Candidates.empty())
401 Decls.reserve(Candidates.size());
402 for (
const Candidate &C : Candidates) {
403 Decl *LookupRes = C.first.get();
410 bool IsSpecImportFailed =
412 assert(!IsSpecImportFailed);
413 (void)IsSpecImportFailed;
424 Source<const DeclContext *> SourceDC) ->
bool {
425 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
426 if (IsKindWeWant(SourceDecl->getKind())) {
427 Decl *ImportedDecl = Forward.
Import(const_cast<Decl *>(SourceDecl));
428 assert(!ImportedDecl || IsSameDC(ImportedDecl->
getDeclContext(), DC));
LLVM_NODISCARD llvm::Error ImportDefinition_New(Decl *From)
Import the definition of the given declaration, including all of the declarations it contains...
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...
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...
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
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 ...
QualType Import(QualType FromT)
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.
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 * getDeclContext()
DeclContext * getParent()
getParent - Returns the containing DeclContext.
The result type of a method or function.
Decl::Kind getDeclKind() const
ASTImporter & ImporterForOrigin(ASTContext &OriginContext)
Returns a reference to the ASTRImporter from Importers whose origin is OriginContext.
Represents the declaration of a struct/union/class/enum.
ASTContext & getASTContext() const LLVM_READONLY
bool hasExternalLexicalStorage() const
Whether this DeclContext has external storage containing additional declarations that are lexically i...
std::map< const DeclContext *, DCOrigin > OriginMap
A source for an ExternalASTMerger.
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.
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...
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)