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