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 Source<DeclarationName> SourceName = ReverseImporter.
Import(Name);
61 SourceParentDC.get()->lookup(SourceName.get());
62 size_t SearchResultSize = SearchResult.
size();
63 if (SearchResultSize == 0 || SearchResultSize > 1) {
75 NamedDecl *SearchResultDecl = SearchResult[0];
76 if (isa<DeclContext>(SearchResultDecl) &&
78 return cast<DeclContext>(SearchResultDecl)->getPrimaryContext();
100 llvm::raw_ostream &logs() {
return Parent.
logs(); }
106 :
ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
108 Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
109 ToFileManager,
true), FromOrigins(_FromOrigins) {}
114 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
117 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
118 <<
" imported (DeclContext*)" << (
void*)ToDC
119 <<
", (ASTContext*)" << (
void*)&getToContext()
120 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
121 <<
", (ASTContext*)" << (
void*)&getFromContext()
123 Source<DeclContext *> FromDC(
125 if (FromOrigins.count(FromDC) &&
128 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
129 <<
" forced origin (DeclContext*)" 130 << (
void*)FromOrigins.at(FromDC).DC
132 << (
void*)FromOrigins.at(FromDC).AST
137 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
138 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
139 <<
", (ASTContext*)" << (
void*)&getFromContext()
144 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
145 ToTag->setHasExternalLexicalStorage();
146 ToTag->setMustBuildLookupTable();
148 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
149 ToNamespace->setHasExternalVisibleStorage();
151 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
152 ToContainer->setHasExternalLexicalStorage();
153 ToContainer->setMustBuildLookupTable();
162 if (isa<FunctionDecl>(C.first.get()))
164 return llvm::any_of(Decls, [&](
const Candidate &D) {
165 return C.first.get()->getKind() == D.first.get()->getKind();
172 for (
const std::unique_ptr<ASTImporter> &I : Importers)
173 if (&I->getFromContext() == &OriginContext)
175 llvm_unreachable(
"We should have an importer for this origin!");
181 return static_cast<LazyASTImporter &
>(
187 for (
const std::unique_ptr<ASTImporter> &I : Importers)
188 if (&I->getFromContext() == &OriginContext)
193 template <
typename CallbackType>
194 void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
195 CallbackType Callback) {
196 if (Origins.count(DC)) {
198 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
199 Callback(Importer, Importer.GetReverse(), Origin.
DC);
201 bool DidCallback =
false;
202 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
203 Source<TranslationUnitDecl *> SourceTU =
204 Importer->getFromContext().getTranslationUnitDecl();
206 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
207 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
209 if (Callback(*Importer, Reverse, SourceDC))
213 if (!DidCallback && LoggingEnabled())
214 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 215 <<
" asserting for (DeclContext*)" << (
const void*)DC
216 <<
", (ASTContext*)" << (
void*)&Target.AST
218 assert(DidCallback &&
"Couldn't find a source context matching our DC");
225 Source<const DeclContext *> SourceDC) ->
bool {
226 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
227 if (SourceTag->hasExternalLexicalStorage())
229 if (!SourceTag->getDefinition())
242 Source<const DeclContext *> SourceDC) ->
bool {
244 cast<ObjCInterfaceDecl>(SourceDC.get()));
245 if (SourceInterface->hasExternalLexicalStorage())
248 if (!SourceInterface->getDefinition())
250 Forward.
Imported(SourceInterface, Interface);
259 bool FoundMatchingDC =
false;
260 ForEachMatchingDC(Interface,
262 Source<const DeclContext *> SourceDC) ->
bool {
263 FoundMatchingDC =
true;
266 return FoundMatchingDC;
271 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
273 if (
auto *T1 = dyn_cast<TagDecl>(D1))
274 if (
auto *T2 = dyn_cast<TagDecl>(D2))
275 if (T1->getFirstDecl() == T2->getFirstDecl())
277 return D1 == D2 || D1 == CanonicalizeDC(D2);
283 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
285 Source<const DeclContext *> FoundFromDC =
287 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
289 RecordOriginImpl(ToDC, Origin, Importer);
290 if (LoggingEnabled())
291 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 292 << (DoRecord ?
" decided " :
" decided NOT")
293 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC 294 <<
", (ASTContext*)" << (
void*)&Origin.
AST 300 RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.
AST));
305 Origins[ToDC] = Origin;
306 Importer.ASTImporter::Imported(cast<Decl>(Origin.
DC), const_cast<Decl*>(cast<Decl>(ToDC)));
316 assert(&S.AST != &Target.
AST);
317 Importers.push_back(llvm::make_unique<LazyASTImporter>(
318 *
this, Target.
AST, Target.
FM, S.AST, S.FM, S.OM));
325 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 326 <<
" removing source (ASTContext*)" << (
void*)&S.AST
329 std::remove_if(Importers.begin(), Importers.end(),
330 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
338 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
339 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
342 if (&S.AST == Origin.second.AST) {
348 OI = Origins.erase(OI);
359 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
360 if (!HasDeclOfSameType(Candidates, C))
361 Candidates.push_back(C);
365 Source<const DeclContext *> SourceDC) ->
bool {
369 FilterFoundDecl(std::make_pair(FromD, &Forward));
374 if (Candidates.empty())
377 Decls.reserve(Candidates.size());
378 for (
const Candidate &C : Candidates) {
379 NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
391 Source<const DeclContext *> SourceDC) ->
bool {
392 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
393 if (IsKindWeWant(SourceDecl->getKind())) {
394 Decl *ImportedDecl = Forward.
Import(const_cast<Decl *>(SourceDecl));
395 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.
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();.
A single origin for a DeclContext.
bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override
Implementation of the ExternalASTSource API.
const FunctionProtoType * T
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.
TagDecl - 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...
virtual Decl * Imported(Decl *From, Decl *To)
Note that we have imported the "from" declaration by mapping it to the (potentially-newly-created) "t...
bool CanComplete(DeclContext *DC)
Returns true if DC can be found in any source AST context.
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.
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...
NamedDecl - This represents a decl with a name.
bool isTranslationUnit() const
ExternalASTSource implementation that merges information from several ASTContexts.
ExternalASTMerger(const ImporterTarget &Target, llvm::ArrayRef< ImporterSource > Sources)