ExternalASTMerger.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. //===- ExternalASTMerger.cpp - Merging External AST Interface ---*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the ExternalASTMerger, which vends a combination of
  11. // ASTs from several different ASTContext/FileManager pairs
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/AST/ASTContext.h"
  15. #include "clang/AST/Decl.h"
  16. #include "clang/AST/DeclObjC.h"
  17. #include "clang/AST/ExternalASTMerger.h"
  18. using namespace clang;
  19. namespace {
  20. template <typename T> struct Source {
  21. T t;
  22. Source(T t) : t(t) {}
  23. operator T() { return t; }
  24. template <typename U = T> U &get() { return t; }
  25. template <typename U = T> const U &get() const { return t; }
  26. template <typename U> operator Source<U>() { return Source<U>(t); }
  27. };
  28. typedef std::pair<Source<NamedDecl *>, ASTImporter *> Candidate;
  29. class LazyASTImporter : public ASTImporter {
  30. public:
  31. LazyASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
  32. ASTContext &FromContext, FileManager &FromFileManager)
  33. : ASTImporter(ToContext, ToFileManager, FromContext, FromFileManager,
  34. /*MinimalImport=*/true) {}
  35. Decl *Imported(Decl *From, Decl *To) override {
  36. if (auto ToTag = dyn_cast<TagDecl>(To)) {
  37. ToTag->setHasExternalLexicalStorage();
  38. ToTag->setMustBuildLookupTable();
  39. } else if (auto ToNamespace = dyn_cast<NamespaceDecl>(To)) {
  40. ToNamespace->setHasExternalVisibleStorage();
  41. }
  42. return ASTImporter::Imported(From, To);
  43. }
  44. };
  45. Source<const DeclContext *>
  46. LookupSameContext(Source<TranslationUnitDecl *> SourceTU, const DeclContext *DC,
  47. ASTImporter &ReverseImporter) {
  48. if (DC->isTranslationUnit()) {
  49. return SourceTU;
  50. }
  51. Source<const DeclContext *> SourceParentDC =
  52. LookupSameContext(SourceTU, DC->getParent(), ReverseImporter);
  53. if (!SourceParentDC) {
  54. // If we couldn't find the parent DC in this TranslationUnit, give up.
  55. return nullptr;
  56. }
  57. auto ND = cast<NamedDecl>(DC);
  58. DeclarationName Name = ND->getDeclName();
  59. Source<DeclarationName> SourceName = ReverseImporter.Import(Name);
  60. DeclContext::lookup_result SearchResult =
  61. SourceParentDC.get()->lookup(SourceName.get());
  62. size_t SearchResultSize = SearchResult.size();
  63. // Handle multiple candidates once we have a test for it.
  64. // This may turn up when we import template specializations correctly.
  65. assert(SearchResultSize < 2);
  66. if (SearchResultSize == 0) {
  67. // couldn't find the name, so we have to give up
  68. return nullptr;
  69. } else {
  70. NamedDecl *SearchResultDecl = SearchResult[0];
  71. return dyn_cast<DeclContext>(SearchResultDecl);
  72. }
  73. }
  74. bool IsForwardDeclaration(Decl *D) {
  75. assert(!isa<ObjCInterfaceDecl>(D)); // TODO handle this case
  76. if (auto TD = dyn_cast<TagDecl>(D)) {
  77. return !TD->isThisDeclarationADefinition();
  78. } else if (auto FD = dyn_cast<FunctionDecl>(D)) {
  79. return !FD->isThisDeclarationADefinition();
  80. } else {
  81. return false;
  82. }
  83. }
  84. template <typename CallbackType>
  85. void ForEachMatchingDC(
  86. const DeclContext *DC,
  87. llvm::ArrayRef<ExternalASTMerger::ImporterPair> Importers,
  88. CallbackType Callback) {
  89. for (const ExternalASTMerger::ImporterPair &IP : Importers) {
  90. Source<TranslationUnitDecl *> SourceTU =
  91. IP.Forward->getFromContext().getTranslationUnitDecl();
  92. if (auto SourceDC = LookupSameContext(SourceTU, DC, *IP.Reverse))
  93. Callback(IP, SourceDC);
  94. }
  95. }
  96. bool HasDeclOfSameType(llvm::ArrayRef<Candidate> Decls, const Candidate &C) {
  97. return llvm::any_of(Decls, [&](const Candidate &D) {
  98. return C.first.get()->getKind() == D.first.get()->getKind();
  99. });
  100. }
  101. } // end namespace
  102. ExternalASTMerger::ExternalASTMerger(const ImporterEndpoint &Target,
  103. llvm::ArrayRef<ImporterEndpoint> Sources) {
  104. for (const ImporterEndpoint &S : Sources) {
  105. Importers.push_back(
  106. {llvm::make_unique<LazyASTImporter>(Target.AST, Target.FM, S.AST, S.FM),
  107. llvm::make_unique<ASTImporter>(S.AST, S.FM, Target.AST, Target.FM,
  108. /*MinimalImport=*/true)});
  109. }
  110. }
  111. bool ExternalASTMerger::FindExternalVisibleDeclsByName(const DeclContext *DC,
  112. DeclarationName Name) {
  113. llvm::SmallVector<NamedDecl *, 1> Decls;
  114. llvm::SmallVector<Candidate, 4> CompleteDecls;
  115. llvm::SmallVector<Candidate, 4> ForwardDecls;
  116. auto FilterFoundDecl = [&CompleteDecls, &ForwardDecls](const Candidate &C) {
  117. if (IsForwardDeclaration(C.first.get())) {
  118. if (!HasDeclOfSameType(ForwardDecls, C)) {
  119. ForwardDecls.push_back(C);
  120. }
  121. } else {
  122. CompleteDecls.push_back(C);
  123. }
  124. };
  125. ForEachMatchingDC(
  126. DC, Importers,
  127. [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
  128. DeclarationName FromName = IP.Reverse->Import(Name);
  129. DeclContextLookupResult Result = SourceDC.get()->lookup(FromName);
  130. for (NamedDecl *FromD : Result) {
  131. FilterFoundDecl(std::make_pair(FromD, IP.Forward.get()));
  132. }
  133. });
  134. llvm::ArrayRef<Candidate> DeclsToReport =
  135. CompleteDecls.empty() ? ForwardDecls : CompleteDecls;
  136. if (DeclsToReport.empty()) {
  137. return false;
  138. }
  139. Decls.reserve(DeclsToReport.size());
  140. for (const Candidate &C : DeclsToReport) {
  141. NamedDecl *d = cast<NamedDecl>(C.second->Import(C.first.get()));
  142. assert(d);
  143. Decls.push_back(d);
  144. }
  145. SetExternalVisibleDeclsForName(DC, Name, Decls);
  146. return true;
  147. }
  148. void ExternalASTMerger::FindExternalLexicalDecls(
  149. const DeclContext *DC, llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
  150. SmallVectorImpl<Decl *> &Result) {
  151. ForEachMatchingDC(
  152. DC, Importers,
  153. [&](const ImporterPair &IP, Source<const DeclContext *> SourceDC) {
  154. for (const Decl *SourceDecl : SourceDC.get()->decls()) {
  155. if (IsKindWeWant(SourceDecl->getKind())) {
  156. Decl *ImportedDecl =
  157. IP.Forward->Import(const_cast<Decl *>(SourceDecl));
  158. assert(ImportedDecl->getDeclContext() == DC);
  159. (void)ImportedDecl;
  160. }
  161. }
  162. });
  163. }
  164. void ExternalASTMerger::CompleteType(TagDecl *Tag) {
  165. SmallVector<Decl *, 0> Result;
  166. FindExternalLexicalDecls(Tag, [](Decl::Kind) { return true; }, Result);
  167. Tag->setHasExternalLexicalStorage(false);
  168. }