1 //===- ASTImporterLookupTable.cpp - ASTImporter specific lookup -----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the ASTImporterLookupTable class which implements a
11 //  lookup procedure for the import mechanism.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/AST/ASTImporterLookupTable.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/RecursiveASTVisitor.h"
18 
19 namespace clang {
20 
21 namespace {
22 
23 struct Builder : RecursiveASTVisitor<Builder> {
24   ASTImporterLookupTable &LT;
25   Builder(ASTImporterLookupTable &LT) : LT(LT) {}
26   bool VisitNamedDecl(NamedDecl *D) {
27     LT.add(D);
28     return true;
29   }
30   bool VisitFriendDecl(FriendDecl *D) {
31     if (D->getFriendType()) {
32       QualType Ty = D->getFriendType()->getType();
33       // FIXME Can this be other than elaborated?
34       QualType NamedTy = cast<ElaboratedType>(Ty)->getNamedType();
35       if (!NamedTy->isDependentType()) {
36         if (const auto *RTy = dyn_cast<RecordType>(NamedTy))
37           LT.add(RTy->getAsCXXRecordDecl());
38         else if (const auto *SpecTy =
39                      dyn_cast<TemplateSpecializationType>(NamedTy)) {
40           LT.add(SpecTy->getAsCXXRecordDecl());
41         }
42       }
43     }
44     return true;
45   }
46 
47   // Override default settings of base.
48   bool shouldVisitTemplateInstantiations() const { return true; }
49   bool shouldVisitImplicitCode() const { return true; }
50 };
51 
52 } // anonymous namespace
53 
54 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
55   Builder B(*this);
56   B.TraverseDecl(&TU);
57 }
58 
59 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
60   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
61   // Inserts if and only if there is no element in the container equal to it.
62   Decls.insert(ND);
63 }
64 
65 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
66   DeclList &Decls = LookupTable[DC][ND->getDeclName()];
67   bool EraseResult = Decls.remove(ND);
68   (void)EraseResult;
69   assert(EraseResult == true && "Trying to remove not contained Decl");
70 }
71 
72 void ASTImporterLookupTable::add(NamedDecl *ND) {
73   assert(ND);
74   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
75   add(DC, ND);
76   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
77   if (DC != ReDC)
78     add(ReDC, ND);
79 }
80 
81 void ASTImporterLookupTable::remove(NamedDecl *ND) {
82   assert(ND);
83   DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
84   remove(DC, ND);
85   DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
86   if (DC != ReDC)
87     remove(ReDC, ND);
88 }
89 
90 ASTImporterLookupTable::LookupResult
91 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
92   auto DCI = LookupTable.find(DC->getPrimaryContext());
93   if (DCI == LookupTable.end())
94     return {};
95 
96   const auto &FoundNameMap = DCI->second;
97   auto NamesI = FoundNameMap.find(Name);
98   if (NamesI == FoundNameMap.end())
99     return {};
100 
101   return NamesI->second;
102 }
103 
104 void ASTImporterLookupTable::dump(DeclContext *DC) const {
105   auto DCI = LookupTable.find(DC->getPrimaryContext());
106   if (DCI == LookupTable.end())
107     llvm::errs() << "empty\n";
108   const auto &FoundNameMap = DCI->second;
109   for (const auto &Entry : FoundNameMap) {
110     DeclarationName Name = Entry.first;
111     llvm::errs() << "==== Name: ";
112     Name.dump();
113     const DeclList& List = Entry.second;
114     for (NamedDecl *ND : List) {
115       ND->dump();
116     }
117   }
118 }
119 
120 void ASTImporterLookupTable::dump() const {
121   for (const auto &Entry : LookupTable) {
122     DeclContext *DC = Entry.first;
123     StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
124     llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
125     dump(DC);
126   }
127 }
128 
129 } // namespace clang
130