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 llvm::raw_ostream &logs() {
return Parent.
logs(); }
111 :
ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
113 Parent(_Parent), Reverse(FromContext, FromFileManager, ToContext,
114 ToFileManager,
true), FromOrigins(_FromOrigins) {}
118 void Imported(
Decl *From,
Decl *To)
override {
119 if (
auto *ToDC = dyn_cast<DeclContext>(To)) {
122 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
123 <<
" imported (DeclContext*)" << (
void*)ToDC
124 <<
", (ASTContext*)" << (
void*)&getToContext()
125 <<
" from (DeclContext*)" << (
void*)llvm::cast<DeclContext>(From)
126 <<
", (ASTContext*)" << (
void*)&getFromContext()
128 Source<DeclContext *> FromDC(
130 if (FromOrigins.count(FromDC) &&
133 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
134 <<
" forced origin (DeclContext*)" 135 << (
void*)FromOrigins.at(FromDC).DC
137 << (
void*)FromOrigins.at(FromDC).AST
142 logs() <<
"(ExternalASTMerger*)" << (
void*)&Parent
143 <<
" maybe recording origin (DeclContext*)" << (
void*)FromDC
144 <<
", (ASTContext*)" << (
void*)&getFromContext()
149 if (
auto *ToTag = dyn_cast<TagDecl>(To)) {
150 ToTag->setHasExternalLexicalStorage();
151 ToTag->getPrimaryContext()->setMustBuildLookupTable();
153 }
else if (
auto *ToNamespace = dyn_cast<NamespaceDecl>(To)) {
154 ToNamespace->setHasExternalVisibleStorage();
156 }
else if (
auto *ToContainer = dyn_cast<ObjCContainerDecl>(To)) {
157 ToContainer->setHasExternalLexicalStorage();
158 ToContainer->getPrimaryContext()->setMustBuildLookupTable();
166 if (isa<FunctionDecl>(C.first.get()))
168 return llvm::any_of(Decls, [&](
const Candidate &D) {
169 return C.first.get()->getKind() == D.first.get()->getKind();
176 for (
const std::unique_ptr<ASTImporter> &I : Importers)
177 if (&I->getFromContext() == &OriginContext)
179 llvm_unreachable(
"We should have an importer for this origin!");
185 return static_cast<LazyASTImporter &
>(
191 for (
const std::unique_ptr<ASTImporter> &I : Importers)
192 if (&I->getFromContext() == &OriginContext)
197 template <
typename CallbackType>
198 void ExternalASTMerger::ForEachMatchingDC(
const DeclContext *DC,
199 CallbackType Callback) {
200 if (Origins.count(DC)) {
202 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
203 Callback(Importer, Importer.GetReverse(), Origin.
DC);
205 bool DidCallback =
false;
206 for (
const std::unique_ptr<ASTImporter> &Importer : Importers) {
207 Source<TranslationUnitDecl *> SourceTU =
208 Importer->getFromContext().getTranslationUnitDecl();
210 static_cast<LazyASTImporter *
>(Importer.get())->GetReverse();
211 if (
auto SourceDC = LookupSameContext(SourceTU, DC, Reverse)) {
213 if (Callback(*Importer, Reverse, SourceDC))
217 if (!DidCallback && LoggingEnabled())
218 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 219 <<
" asserting for (DeclContext*)" << (
const void*)DC
220 <<
", (ASTContext*)" << (
void*)&
Target.AST
222 assert(DidCallback &&
"Couldn't find a source context matching our DC");
229 Source<const DeclContext *> SourceDC) ->
bool {
230 auto *SourceTag =
const_cast<TagDecl *
>(cast<TagDecl>(SourceDC.get()));
231 if (SourceTag->hasExternalLexicalStorage())
233 if (!SourceTag->getDefinition())
237 llvm::consumeError(std::move(Err));
247 Source<const DeclContext *> SourceDC) ->
bool {
249 cast<ObjCInterfaceDecl>(SourceDC.get()));
250 if (SourceInterface->hasExternalLexicalStorage())
253 if (!SourceInterface->getDefinition())
257 llvm::consumeError(std::move(Err));
265 bool FoundMatchingDC =
false;
266 ForEachMatchingDC(Interface,
268 Source<const DeclContext *> SourceDC) ->
bool {
269 FoundMatchingDC =
true;
272 return FoundMatchingDC;
277 if (isa<ObjCContainerDecl>(D1) && isa<ObjCContainerDecl>(D2))
279 if (
auto *T1 = dyn_cast<TagDecl>(D1))
280 if (
auto *T2 = dyn_cast<TagDecl>(D2))
281 if (T1->getFirstDecl() == T2->getFirstDecl())
283 return D1 == D2 || D1 == CanonicalizeDC(D2);
289 LazyASTImporter &Importer = LazyImporterForOrigin(*
this, *Origin.
AST);
291 Source<const DeclContext *> FoundFromDC =
293 const bool DoRecord = !FoundFromDC || !IsSameDC(FoundFromDC.get(), Origin.
DC);
295 RecordOriginImpl(ToDC, Origin, Importer);
296 if (LoggingEnabled())
297 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 298 << (DoRecord ?
" decided " :
" decided NOT")
299 <<
" to record origin (DeclContext*)" << (
void*)Origin.
DC 300 <<
", (ASTContext*)" << (
void*)&Origin.
AST 306 RecordOriginImpl(ToDC, Origin, ImporterForOrigin(*Origin.
AST));
311 Origins[ToDC] = Origin;
312 Importer.ASTImporter::MapImported(cast<Decl>(Origin.
DC), const_cast<Decl*>(cast<Decl>(ToDC)));
322 assert(&S.AST != &Target.
AST);
323 Importers.push_back(llvm::make_unique<LazyASTImporter>(
324 *
this, Target.
AST, Target.
FM, S.AST, S.FM, S.OM));
331 logs() <<
"(ExternalASTMerger*)" << (
void*)
this 332 <<
" removing source (ASTContext*)" << (
void*)&S.AST
335 std::remove_if(Importers.begin(), Importers.end(),
336 [&Sources](std::unique_ptr<ASTImporter> &Importer) ->
bool {
344 for (OriginMap::iterator OI = Origins.begin(), OE = Origins.end(); OI != OE; ) {
345 std::pair<const DeclContext *, DCOrigin> Origin = *OI;
348 if (&S.AST == Origin.second.AST) {
354 OI = Origins.erase(OI);
360 template <
typename DeclTy>
362 for (
auto *Spec : D->specializations()) {
363 auto ImportedSpecOrError = Importer->
Import(Spec);
364 if (!ImportedSpecOrError) {
365 llvm::consumeError(ImportedSpecOrError.takeError());
374 if (!isa<TemplateDecl>(D))
376 if (
auto *FunctionTD = dyn_cast<FunctionTemplateDecl>(D))
378 else if (
auto *ClassTD = dyn_cast<ClassTemplateDecl>(D))
380 else if (
auto *VarTD = dyn_cast<VarTemplateDecl>(D))
390 auto FilterFoundDecl = [&Candidates](
const Candidate &
C) {
391 if (!HasDeclOfSameType(Candidates, C))
392 Candidates.push_back(C);
395 ForEachMatchingDC(DC,
397 Source<const DeclContext *> SourceDC) ->
bool {
398 auto FromNameOrErr = Reverse.
Import(Name);
399 if (!FromNameOrErr) {
400 llvm::consumeError(FromNameOrErr.takeError());
404 SourceDC.get()->lookup(*FromNameOrErr);
406 FilterFoundDecl(std::make_pair(FromD, &Forward));
411 if (Candidates.empty())
414 Decls.reserve(Candidates.size());
415 for (
const Candidate &C : Candidates) {
416 Decl *LookupRes = C.first.get();
418 auto NDOrErr = Importer->
Import(LookupRes);
420 (void)static_cast<bool>(NDOrErr);
421 NamedDecl *ND = cast_or_null<NamedDecl>(*NDOrErr);
426 bool IsSpecImportFailed =
428 assert(!IsSpecImportFailed);
429 (void)IsSpecImportFailed;
440 Source<const DeclContext *> SourceDC) ->
bool {
441 for (
const Decl *SourceDecl : SourceDC.get()->decls()) {
442 if (IsKindWeWant(SourceDecl->getKind())) {
443 auto ImportedDeclOrErr = Forward.
Import(SourceDecl);
444 if (ImportedDeclOrErr)
445 assert(!(*ImportedDeclOrErr) ||
446 IsSameDC((*ImportedDeclOrErr)->getDeclContext(), DC));
448 llvm::consumeError(ImportedDeclOrErr.takeError());
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...
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
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
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
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)