xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/ASTImporterLookupTable.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg //  This file defines the ASTImporterLookupTable class which implements a
107330f729Sjoerg //  lookup procedure for the import mechanism.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg 
147330f729Sjoerg #include "clang/AST/ASTImporterLookupTable.h"
157330f729Sjoerg #include "clang/AST/Decl.h"
167330f729Sjoerg #include "clang/AST/RecursiveASTVisitor.h"
177330f729Sjoerg 
187330f729Sjoerg namespace clang {
197330f729Sjoerg 
207330f729Sjoerg namespace {
217330f729Sjoerg 
227330f729Sjoerg struct Builder : RecursiveASTVisitor<Builder> {
237330f729Sjoerg   ASTImporterLookupTable &LT;
Builderclang::__anond11c4a580111::Builder247330f729Sjoerg   Builder(ASTImporterLookupTable &LT) : LT(LT) {}
25*e038c9c4Sjoerg 
VisitTypedefNameDeclclang::__anond11c4a580111::Builder26*e038c9c4Sjoerg   bool VisitTypedefNameDecl(TypedefNameDecl *D) {
27*e038c9c4Sjoerg     QualType Ty = D->getUnderlyingType();
28*e038c9c4Sjoerg     Ty = Ty.getCanonicalType();
29*e038c9c4Sjoerg     if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
30*e038c9c4Sjoerg       LT.add(RTy->getAsRecordDecl());
31*e038c9c4Sjoerg       // iterate over the field decls, adding them
32*e038c9c4Sjoerg       for (auto *it : RTy->getAsRecordDecl()->fields()) {
33*e038c9c4Sjoerg         LT.add(it);
34*e038c9c4Sjoerg       }
35*e038c9c4Sjoerg     }
36*e038c9c4Sjoerg     return true;
37*e038c9c4Sjoerg   }
38*e038c9c4Sjoerg 
VisitNamedDeclclang::__anond11c4a580111::Builder397330f729Sjoerg   bool VisitNamedDecl(NamedDecl *D) {
407330f729Sjoerg     LT.add(D);
417330f729Sjoerg     return true;
427330f729Sjoerg   }
437330f729Sjoerg   // In most cases the FriendDecl contains the declaration of the befriended
447330f729Sjoerg   // class as a child node, so it is discovered during the recursive
457330f729Sjoerg   // visitation. However, there are cases when the befriended class is not a
467330f729Sjoerg   // child, thus it must be fetched explicitly from the FriendDecl, and only
477330f729Sjoerg   // then can we add it to the lookup table.
VisitFriendDeclclang::__anond11c4a580111::Builder487330f729Sjoerg   bool VisitFriendDecl(FriendDecl *D) {
497330f729Sjoerg     if (D->getFriendType()) {
507330f729Sjoerg       QualType Ty = D->getFriendType()->getType();
517330f729Sjoerg       if (isa<ElaboratedType>(Ty))
527330f729Sjoerg         Ty = cast<ElaboratedType>(Ty)->getNamedType();
537330f729Sjoerg       // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
547330f729Sjoerg       // always has that decl as child node.
557330f729Sjoerg       // However, there are non-dependent cases which does not have the
567330f729Sjoerg       // type as a child node. We have to dig up that type now.
577330f729Sjoerg       if (!Ty->isDependentType()) {
587330f729Sjoerg         if (const auto *RTy = dyn_cast<RecordType>(Ty))
597330f729Sjoerg           LT.add(RTy->getAsCXXRecordDecl());
607330f729Sjoerg         else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
617330f729Sjoerg           LT.add(SpecTy->getAsCXXRecordDecl());
62*e038c9c4Sjoerg         else if (const auto *SubstTy =
63*e038c9c4Sjoerg                      dyn_cast<SubstTemplateTypeParmType>(Ty)) {
64*e038c9c4Sjoerg           if (SubstTy->getAsCXXRecordDecl())
65*e038c9c4Sjoerg             LT.add(SubstTy->getAsCXXRecordDecl());
66*e038c9c4Sjoerg         } else if (isa<TypedefType>(Ty)) {
677330f729Sjoerg           // We do not put friend typedefs to the lookup table because
687330f729Sjoerg           // ASTImporter does not organize typedefs into redecl chains.
697330f729Sjoerg         } else {
707330f729Sjoerg           llvm_unreachable("Unhandled type of friend class");
717330f729Sjoerg         }
727330f729Sjoerg       }
737330f729Sjoerg     }
747330f729Sjoerg     return true;
757330f729Sjoerg   }
767330f729Sjoerg 
777330f729Sjoerg   // Override default settings of base.
shouldVisitTemplateInstantiationsclang::__anond11c4a580111::Builder787330f729Sjoerg   bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCodeclang::__anond11c4a580111::Builder797330f729Sjoerg   bool shouldVisitImplicitCode() const { return true; }
807330f729Sjoerg };
817330f729Sjoerg 
827330f729Sjoerg } // anonymous namespace
837330f729Sjoerg 
ASTImporterLookupTable(TranslationUnitDecl & TU)847330f729Sjoerg ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
857330f729Sjoerg   Builder B(*this);
867330f729Sjoerg   B.TraverseDecl(&TU);
877330f729Sjoerg }
887330f729Sjoerg 
add(DeclContext * DC,NamedDecl * ND)897330f729Sjoerg void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
907330f729Sjoerg   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
917330f729Sjoerg   // Inserts if and only if there is no element in the container equal to it.
927330f729Sjoerg   Decls.insert(ND);
937330f729Sjoerg }
947330f729Sjoerg 
remove(DeclContext * DC,NamedDecl * ND)957330f729Sjoerg void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
967330f729Sjoerg   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
977330f729Sjoerg   bool EraseResult = Decls.remove(ND);
987330f729Sjoerg   (void)EraseResult;
997330f729Sjoerg   assert(EraseResult == true && "Trying to remove not contained Decl");
1007330f729Sjoerg }
1017330f729Sjoerg 
add(NamedDecl * ND)1027330f729Sjoerg void ASTImporterLookupTable::add(NamedDecl *ND) {
1037330f729Sjoerg   assert(ND);
1047330f729Sjoerg   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
1057330f729Sjoerg   add(DC, ND);
1067330f729Sjoerg   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
1077330f729Sjoerg   if (DC != ReDC)
1087330f729Sjoerg     add(ReDC, ND);
1097330f729Sjoerg }
1107330f729Sjoerg 
remove(NamedDecl * ND)1117330f729Sjoerg void ASTImporterLookupTable::remove(NamedDecl *ND) {
1127330f729Sjoerg   assert(ND);
1137330f729Sjoerg   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
1147330f729Sjoerg   remove(DC, ND);
1157330f729Sjoerg   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
1167330f729Sjoerg   if (DC != ReDC)
1177330f729Sjoerg     remove(ReDC, ND);
1187330f729Sjoerg }
1197330f729Sjoerg 
1207330f729Sjoerg ASTImporterLookupTable::LookupResult
lookup(DeclContext * DC,DeclarationName Name) const1217330f729Sjoerg ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
1227330f729Sjoerg   auto DCI = LookupTable.find(DC->getPrimaryContext());
1237330f729Sjoerg   if (DCI == LookupTable.end())
1247330f729Sjoerg     return {};
1257330f729Sjoerg 
1267330f729Sjoerg   const auto &FoundNameMap = DCI->second;
1277330f729Sjoerg   auto NamesI = FoundNameMap.find(Name);
1287330f729Sjoerg   if (NamesI == FoundNameMap.end())
1297330f729Sjoerg     return {};
1307330f729Sjoerg 
1317330f729Sjoerg   return NamesI->second;
1327330f729Sjoerg }
1337330f729Sjoerg 
dump(DeclContext * DC) const1347330f729Sjoerg void ASTImporterLookupTable::dump(DeclContext *DC) const {
1357330f729Sjoerg   auto DCI = LookupTable.find(DC->getPrimaryContext());
1367330f729Sjoerg   if (DCI == LookupTable.end())
1377330f729Sjoerg     llvm::errs() << "empty\n";
1387330f729Sjoerg   const auto &FoundNameMap = DCI->second;
1397330f729Sjoerg   for (const auto &Entry : FoundNameMap) {
1407330f729Sjoerg     DeclarationName Name = Entry.first;
1417330f729Sjoerg     llvm::errs() << "==== Name: ";
1427330f729Sjoerg     Name.dump();
1437330f729Sjoerg     const DeclList& List = Entry.second;
1447330f729Sjoerg     for (NamedDecl *ND : List) {
1457330f729Sjoerg       ND->dump();
1467330f729Sjoerg     }
1477330f729Sjoerg   }
1487330f729Sjoerg }
1497330f729Sjoerg 
dump() const1507330f729Sjoerg void ASTImporterLookupTable::dump() const {
1517330f729Sjoerg   for (const auto &Entry : LookupTable) {
1527330f729Sjoerg     DeclContext *DC = Entry.first;
1537330f729Sjoerg     StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
1547330f729Sjoerg     llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
1557330f729Sjoerg     dump(DC);
1567330f729Sjoerg   }
1577330f729Sjoerg }
1587330f729Sjoerg 
1597330f729Sjoerg } // namespace clang
160