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 bool VisitFriendDecl(FriendDecl *D) { 30 if (D->getFriendType()) { 31 QualType Ty = D->getFriendType()->getType(); 32 // FIXME Can this be other than elaborated? 33 QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType(); 34 if (!NamedTy->isDependentType()) { 35 if (const auto *RTy = dyn_cast<RecordType>(NamedTy)) 36 LT.add(RTy->getAsCXXRecordDecl()); 37 else if (const auto *SpecTy = 38 dyn_cast<TemplateSpecializationType>(NamedTy)) { 39 LT.add(SpecTy->getAsCXXRecordDecl()); 40 } 41 } 42 } 43 return true; 44 } 45 46 // Override default settings of base. 47 bool shouldVisitTemplateInstantiations() const { return true; } 48 bool shouldVisitImplicitCode() const { return true; } 49 }; 50 51 } // anonymous namespace 52 53 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) { 54 Builder B(*this); 55 B.TraverseDecl(&TU); 56 } 57 58 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) { 59 DeclList &Decls = LookupTable[DC][ND->getDeclName()]; 60 // Inserts if and only if there is no element in the container equal to it. 61 Decls.insert(ND); 62 } 63 64 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) { 65 DeclList &Decls = LookupTable[DC][ND->getDeclName()]; 66 bool EraseResult = Decls.remove(ND); 67 (void)EraseResult; 68 assert(EraseResult == true && "Trying to remove not contained Decl"); 69 } 70 71 void ASTImporterLookupTable::add(NamedDecl *ND) { 72 assert(ND); 73 DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); 74 add(DC, ND); 75 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); 76 if (DC != ReDC) 77 add(ReDC, ND); 78 } 79 80 void ASTImporterLookupTable::remove(NamedDecl *ND) { 81 assert(ND); 82 DeclContext *DC = ND->getDeclContext()->getPrimaryContext(); 83 remove(DC, ND); 84 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext(); 85 if (DC != ReDC) 86 remove(ReDC, ND); 87 } 88 89 ASTImporterLookupTable::LookupResult 90 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const { 91 auto DCI = LookupTable.find(DC->getPrimaryContext()); 92 if (DCI == LookupTable.end()) 93 return {}; 94 95 const auto &FoundNameMap = DCI->second; 96 auto NamesI = FoundNameMap.find(Name); 97 if (NamesI == FoundNameMap.end()) 98 return {}; 99 100 return NamesI->second; 101 } 102 103 void ASTImporterLookupTable::dump(DeclContext *DC) const { 104 auto DCI = LookupTable.find(DC->getPrimaryContext()); 105 if (DCI == LookupTable.end()) 106 llvm::errs() << "empty\n"; 107 const auto &FoundNameMap = DCI->second; 108 for (const auto &Entry : FoundNameMap) { 109 DeclarationName Name = Entry.first; 110 llvm::errs() << "==== Name: "; 111 Name.dump(); 112 const DeclList& List = Entry.second; 113 for (NamedDecl *ND : List) { 114 ND->dump(); 115 } 116 } 117 } 118 119 void ASTImporterLookupTable::dump() const { 120 for (const auto &Entry : LookupTable) { 121 DeclContext *DC = Entry.first; 122 StringRef Primary = DC->getPrimaryContext() ? " primary" : ""; 123 llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n"; 124 dump(DC); 125 } 126 } 127 128 } // namespace clang 129