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   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