xref: /freebsd/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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 &LT;
24   Builder(ASTImporterLookupTable &LT) : 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