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->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->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())
243 Source<const DeclContext *> SourceDC) ->
bool {
245 cast<ObjCInterfaceDecl>(SourceDC.get()));
246 if (SourceInterface->hasExternalLexicalStorage())
249 if (!SourceInterface->getDefinition())
260 bool FoundMatchingDC =
false;
261 ForEachMatchingDC(Interface,
263 Source<const DeclContext *> SourceDC) ->
bool {
264 FoundMatchingDC =
true;
267 return FoundMatchingDC;
272 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
274 if (
auto *T1 = dyn_cast<TagDecl>(D1))
275 if (
auto *T2 = dyn_cast<TagDecl>(D2))
276 if (T1->getFirstDecl() == T2->getFirstDecl())
278 return D1 == D2 || D1 == CanonicalizeDC(D2);
284 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
286 Source<const DeclContext *> FoundFromDC =
288 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
290 RecordOriginImpl(ToDC, Origin, Importer);
291 if (LoggingEnabled())
292 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 293 << (DoRecord ?
" decided " :
" decided NOT")
294 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC 295 <<
", (ASTContext*)" << (
void*)&Origin.
AST 301 RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.
AST));
306 Origins[ToDC] = Origin;
307 Importer.ASTImporter::MapImported(cast<Decl>(Origin.
DC), const_cast<Decl*>(cast<Decl>(ToDC)));
317 assert(&S.AST != &Target.
AST);
318 Importers.push_back(llvm::make_unique<LazyASTImporter>(
319 *
this, Target.
AST, Target.
FM, S.AST, S.FM, S.OM));
326 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 327 <<
" removing source (ASTContext*)" << (
void*)&S.AST
330 std::remove_if(Importers.begin(), Importers.end(),
331 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
339 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
340 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
343 if (&S.AST == Origin.second.AST) {
349 OI = Origins.erase(OI);
355 template <
typename DeclTy>
357 for (
auto *Spec : D->specializations())
358 if (!Importer->
Import(Spec))
365 if (!isa<TemplateDecl>(D))
367 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
369 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
371 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
381 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
382 if (!HasDeclOfSameType(Candidates, C))
383 Candidates.push_back(C);
387 Source<const DeclContext *> SourceDC) ->
bool {
391 FilterFoundDecl(std::make_pair(FromD, &Forward));
396 if (Candidates.empty())
399 Decls.reserve(Candidates.size());
400 for (
const Candidate &C : Candidates) {
401 Decl *LookupRes = C.first.get();
408 bool IsSpecImportFailed =
410 assert(!IsSpecImportFailed);
411 (void)IsSpecImportFailed;
422 Source<const DeclContext *> SourceDC) ->
bool {
423 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
424 if (IsKindWeWant(SourceDecl->getKind())) {
425 Decl *ImportedDecl = Forward.
Import(const_cast<Decl *>(SourceDecl));
426 assert(!ImportedDecl || IsSameDC(ImportedDecl->
getDeclContext(), DC));
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...
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)
Import the given type from the "from" context into the "to" context.
static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, ArrayRef< NamedDecl *> Decls)
void setCompleteDefinition(bool V)
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)
DeclarationName - 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 ImportDefinition(Decl *From)
Import the definition of the given declaration, including all of the declarations it contains...
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)