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