ASTImporterLookupTable.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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. namespace clang {
  17. namespace {
  18. struct Builder : RecursiveASTVisitor<Builder> {
  19. ASTImporterLookupTable &LT;
  20. Builder(ASTImporterLookupTable &LT) : LT(LT) {}
  21. bool VisitNamedDecl(NamedDecl *D) {
  22. LT.add(D);
  23. return true;
  24. }
  25. // In most cases the FriendDecl contains the declaration of the befriended
  26. // class as a child node, so it is discovered during the recursive
  27. // visitation. However, there are cases when the befriended class is not a
  28. // child, thus it must be fetched explicitly from the FriendDecl, and only
  29. // then can we add it to the lookup table.
  30. bool VisitFriendDecl(FriendDecl *D) {
  31. if (D->getFriendType()) {
  32. QualType Ty = D->getFriendType()->getType();
  33. if (isa<ElaboratedType>(Ty))
  34. Ty = cast<ElaboratedType>(Ty)->getNamedType();
  35. // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
  36. // always has that decl as child node.
  37. // However, there are non-dependent cases which does not have the
  38. // type as a child node. We have to dig up that type now.
  39. if (!Ty->isDependentType()) {
  40. if (const auto *RTy = dyn_cast<RecordType>(Ty))
  41. LT.add(RTy->getAsCXXRecordDecl());
  42. else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
  43. LT.add(SpecTy->getAsCXXRecordDecl());
  44. else if (isa<TypedefType>(Ty)) {
  45. // We do not put friend typedefs to the lookup table because
  46. // ASTImporter does not organize typedefs into redecl chains.
  47. } else {
  48. llvm_unreachable("Unhandled type of friend class");
  49. }
  50. }
  51. }
  52. return true;
  53. }
  54. // Override default settings of base.
  55. bool shouldVisitTemplateInstantiations() const { return true; }
  56. bool shouldVisitImplicitCode() const { return true; }
  57. };
  58. } // anonymous namespace
  59. ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
  60. Builder B(*this);
  61. B.TraverseDecl(&TU);
  62. }
  63. void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
  64. DeclList &Decls = LookupTable[DC][ND->getDeclName()];
  65. // Inserts if and only if there is no element in the container equal to it.
  66. Decls.insert(ND);
  67. }
  68. void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
  69. DeclList &Decls = LookupTable[DC][ND->getDeclName()];
  70. bool EraseResult = Decls.remove(ND);
  71. (void)EraseResult;
  72. assert(EraseResult == true && "Trying to remove not contained Decl");
  73. }
  74. void ASTImporterLookupTable::add(NamedDecl *ND) {
  75. assert(ND);
  76. DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
  77. add(DC, ND);
  78. DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
  79. if (DC != ReDC)
  80. add(ReDC, ND);
  81. }
  82. void ASTImporterLookupTable::remove(NamedDecl *ND) {
  83. assert(ND);
  84. DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
  85. remove(DC, ND);
  86. DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
  87. if (DC != ReDC)
  88. remove(ReDC, ND);
  89. }
  90. ASTImporterLookupTable::LookupResult
  91. ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
  92. auto DCI = LookupTable.find(DC->getPrimaryContext());
  93. if (DCI == LookupTable.end())
  94. return {};
  95. const auto &FoundNameMap = DCI->second;
  96. auto NamesI = FoundNameMap.find(Name);
  97. if (NamesI == FoundNameMap.end())
  98. return {};
  99. return NamesI->second;
  100. }
  101. void ASTImporterLookupTable::dump(DeclContext *DC) const {
  102. auto DCI = LookupTable.find(DC->getPrimaryContext());
  103. if (DCI == LookupTable.end())
  104. llvm::errs() << "empty\n";
  105. const auto &FoundNameMap = DCI->second;
  106. for (const auto &Entry : FoundNameMap) {
  107. DeclarationName Name = Entry.first;
  108. llvm::errs() << "==== Name: ";
  109. Name.dump();
  110. const DeclList& List = Entry.second;
  111. for (NamedDecl *ND : List) {
  112. ND->dump();
  113. }
  114. }
  115. }
  116. void ASTImporterLookupTable::dump() const {
  117. for (const auto &Entry : LookupTable) {
  118. DeclContext *DC = Entry.first;
  119. StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
  120. llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
  121. dump(DC);
  122. }
  123. }
  124. } // namespace clang