ASTImporterLookupTable.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the ASTImporterLookupTable class which implements a
  10. // lookup procedure for the import mechanism.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/AST/ASTImporterLookupTable.h"
  14. #include "clang/AST/Decl.h"
  15. #include "clang/AST/RecursiveASTVisitor.h"
  16. #include "llvm/Support/FormatVariadic.h"
  17. namespace clang {
  18. namespace {
  19. struct Builder : RecursiveASTVisitor<Builder> {
  20. ASTImporterLookupTable &LT;
  21. Builder(ASTImporterLookupTable &LT) : LT(LT) {}
  22. bool VisitTypedefNameDecl(TypedefNameDecl *D) {
  23. QualType Ty = D->getUnderlyingType();
  24. Ty = Ty.getCanonicalType();
  25. if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
  26. LT.add(RTy->getAsRecordDecl());
  27. // iterate over the field decls, adding them
  28. for (auto *it : RTy->getAsRecordDecl()->fields()) {
  29. LT.add(it);
  30. }
  31. }
  32. return true;
  33. }
  34. bool VisitNamedDecl(NamedDecl *D) {
  35. LT.add(D);
  36. return true;
  37. }
  38. // In most cases the FriendDecl contains the declaration of the befriended
  39. // class as a child node, so it is discovered during the recursive
  40. // visitation. However, there are cases when the befriended class is not a
  41. // child, thus it must be fetched explicitly from the FriendDecl, and only
  42. // then can we add it to the lookup table.
  43. bool VisitFriendDecl(FriendDecl *D) {
  44. if (D->getFriendType()) {
  45. QualType Ty = D->getFriendType()->getType();
  46. if (isa<ElaboratedType>(Ty))
  47. Ty = cast<ElaboratedType>(Ty)->getNamedType();
  48. // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
  49. // always has that decl as child node.
  50. // However, there are non-dependent cases which does not have the
  51. // type as a child node. We have to dig up that type now.
  52. if (!Ty->isDependentType()) {
  53. if (const auto *RTy = dyn_cast<RecordType>(Ty))
  54. LT.add(RTy->getAsCXXRecordDecl());
  55. else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
  56. LT.add(SpecTy->getAsCXXRecordDecl());
  57. else if (const auto *SubstTy =
  58. dyn_cast<SubstTemplateTypeParmType>(Ty)) {
  59. if (SubstTy->getAsCXXRecordDecl())
  60. LT.add(SubstTy->getAsCXXRecordDecl());
  61. } else if (isa<TypedefType>(Ty)) {
  62. // We do not put friend typedefs to the lookup table because
  63. // ASTImporter does not organize typedefs into redecl chains.
  64. } else {
  65. llvm_unreachable("Unhandled type of friend class");
  66. }
  67. }
  68. }
  69. return true;
  70. }
  71. // Override default settings of base.
  72. bool shouldVisitTemplateInstantiations() const { return true; }
  73. bool shouldVisitImplicitCode() const { return true; }
  74. };
  75. } // anonymous namespace
  76. ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
  77. Builder B(*this);
  78. B.TraverseDecl(&TU);
  79. }
  80. void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
  81. DeclList &Decls = LookupTable[DC][ND->getDeclName()];
  82. // Inserts if and only if there is no element in the container equal to it.
  83. Decls.insert(ND);
  84. }
  85. void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
  86. const DeclarationName Name = ND->getDeclName();
  87. DeclList &Decls = LookupTable[DC][Name];
  88. bool EraseResult = Decls.remove(ND);
  89. (void)EraseResult;
  90. #ifndef NDEBUG
  91. if (!EraseResult) {
  92. std::string Message =
  93. llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
  94. Name.getAsString(), DC->getDeclKindName())
  95. .str();
  96. llvm_unreachable(Message.c_str());
  97. }
  98. #endif
  99. }
  100. void ASTImporterLookupTable::add(NamedDecl *ND) {
  101. assert(ND);
  102. DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
  103. add(DC, ND);
  104. DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
  105. if (DC != ReDC)
  106. add(ReDC, ND);
  107. }
  108. void ASTImporterLookupTable::remove(NamedDecl *ND) {
  109. assert(ND);
  110. DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
  111. remove(DC, ND);
  112. DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
  113. if (DC != ReDC)
  114. remove(ReDC, ND);
  115. }
  116. void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {
  117. assert(OldDC != ND->getDeclContext() &&
  118. "DeclContext should be changed before update");
  119. if (contains(ND->getDeclContext(), ND)) {
  120. assert(!contains(OldDC, ND) &&
  121. "Decl should not be found in the old context if already in the new");
  122. return;
  123. }
  124. remove(OldDC, ND);
  125. add(ND);
  126. }
  127. void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) {
  128. LookupTable[OldDC][ND->getDeclName()].remove(ND);
  129. add(ND);
  130. }
  131. ASTImporterLookupTable::LookupResult
  132. ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
  133. auto DCI = LookupTable.find(DC->getPrimaryContext());
  134. if (DCI == LookupTable.end())
  135. return {};
  136. const auto &FoundNameMap = DCI->second;
  137. auto NamesI = FoundNameMap.find(Name);
  138. if (NamesI == FoundNameMap.end())
  139. return {};
  140. return NamesI->second;
  141. }
  142. bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
  143. return lookup(DC, ND->getDeclName()).contains(ND);
  144. }
  145. void ASTImporterLookupTable::dump(DeclContext *DC) const {
  146. auto DCI = LookupTable.find(DC->getPrimaryContext());
  147. if (DCI == LookupTable.end())
  148. llvm::errs() << "empty\n";
  149. const auto &FoundNameMap = DCI->second;
  150. for (const auto &Entry : FoundNameMap) {
  151. DeclarationName Name = Entry.first;
  152. llvm::errs() << "==== Name: ";
  153. Name.dump();
  154. const DeclList& List = Entry.second;
  155. for (NamedDecl *ND : List) {
  156. ND->dump();
  157. }
  158. }
  159. }
  160. void ASTImporterLookupTable::dump() const {
  161. for (const auto &Entry : LookupTable) {
  162. DeclContext *DC = Entry.first;
  163. StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
  164. llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
  165. dump(DC);
  166. }
  167. }
  168. } // namespace clang