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 <
Builderclang::__anond11c4a580111::Builder24 Builder(ASTImporterLookupTable <) : LT(LT) {}
25
VisitTypedefNameDeclclang::__anond11c4a580111::Builder26 bool VisitTypedefNameDecl(TypedefNameDecl *D) {
27 QualType Ty = D->getUnderlyingType();
28 Ty = Ty.getCanonicalType();
29 if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
30 LT.add(RTy->getAsRecordDecl());
31 // iterate over the field decls, adding them
32 for (auto *it : RTy->getAsRecordDecl()->fields()) {
33 LT.add(it);
34 }
35 }
36 return true;
37 }
38
VisitNamedDeclclang::__anond11c4a580111::Builder39 bool VisitNamedDecl(NamedDecl *D) {
40 LT.add(D);
41 return true;
42 }
43 // In most cases the FriendDecl contains the declaration of the befriended
44 // class as a child node, so it is discovered during the recursive
45 // visitation. However, there are cases when the befriended class is not a
46 // child, thus it must be fetched explicitly from the FriendDecl, and only
47 // then can we add it to the lookup table.
VisitFriendDeclclang::__anond11c4a580111::Builder48 bool VisitFriendDecl(FriendDecl *D) {
49 if (D->getFriendType()) {
50 QualType Ty = D->getFriendType()->getType();
51 if (isa<ElaboratedType>(Ty))
52 Ty = cast<ElaboratedType>(Ty)->getNamedType();
53 // A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
54 // always has that decl as child node.
55 // However, there are non-dependent cases which does not have the
56 // type as a child node. We have to dig up that type now.
57 if (!Ty->isDependentType()) {
58 if (const auto *RTy = dyn_cast<RecordType>(Ty))
59 LT.add(RTy->getAsCXXRecordDecl());
60 else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
61 LT.add(SpecTy->getAsCXXRecordDecl());
62 else if (const auto *SubstTy =
63 dyn_cast<SubstTemplateTypeParmType>(Ty)) {
64 if (SubstTy->getAsCXXRecordDecl())
65 LT.add(SubstTy->getAsCXXRecordDecl());
66 } else if (isa<TypedefType>(Ty)) {
67 // We do not put friend typedefs to the lookup table because
68 // ASTImporter does not organize typedefs into redecl chains.
69 } else {
70 llvm_unreachable("Unhandled type of friend class");
71 }
72 }
73 }
74 return true;
75 }
76
77 // Override default settings of base.
shouldVisitTemplateInstantiationsclang::__anond11c4a580111::Builder78 bool shouldVisitTemplateInstantiations() const { return true; }
shouldVisitImplicitCodeclang::__anond11c4a580111::Builder79 bool shouldVisitImplicitCode() const { return true; }
80 };
81
82 } // anonymous namespace
83
ASTImporterLookupTable(TranslationUnitDecl & TU)84 ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
85 Builder B(*this);
86 B.TraverseDecl(&TU);
87 }
88
add(DeclContext * DC,NamedDecl * ND)89 void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
90 DeclList &Decls = LookupTable[DC][ND->getDeclName()];
91 // Inserts if and only if there is no element in the container equal to it.
92 Decls.insert(ND);
93 }
94
remove(DeclContext * DC,NamedDecl * ND)95 void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
96 DeclList &Decls = LookupTable[DC][ND->getDeclName()];
97 bool EraseResult = Decls.remove(ND);
98 (void)EraseResult;
99 assert(EraseResult == true && "Trying to remove not contained Decl");
100 }
101
add(NamedDecl * ND)102 void ASTImporterLookupTable::add(NamedDecl *ND) {
103 assert(ND);
104 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
105 add(DC, ND);
106 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
107 if (DC != ReDC)
108 add(ReDC, ND);
109 }
110
remove(NamedDecl * ND)111 void ASTImporterLookupTable::remove(NamedDecl *ND) {
112 assert(ND);
113 DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
114 remove(DC, ND);
115 DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
116 if (DC != ReDC)
117 remove(ReDC, ND);
118 }
119
120 ASTImporterLookupTable::LookupResult
lookup(DeclContext * DC,DeclarationName Name) const121 ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
122 auto DCI = LookupTable.find(DC->getPrimaryContext());
123 if (DCI == LookupTable.end())
124 return {};
125
126 const auto &FoundNameMap = DCI->second;
127 auto NamesI = FoundNameMap.find(Name);
128 if (NamesI == FoundNameMap.end())
129 return {};
130
131 return NamesI->second;
132 }
133
dump(DeclContext * DC) const134 void ASTImporterLookupTable::dump(DeclContext *DC) const {
135 auto DCI = LookupTable.find(DC->getPrimaryContext());
136 if (DCI == LookupTable.end())
137 llvm::errs() << "empty\n";
138 const auto &FoundNameMap = DCI->second;
139 for (const auto &Entry : FoundNameMap) {
140 DeclarationName Name = Entry.first;
141 llvm::errs() << "==== Name: ";
142 Name.dump();
143 const DeclList& List = Entry.second;
144 for (NamedDecl *ND : List) {
145 ND->dump();
146 }
147 }
148 }
149
dump() const150 void ASTImporterLookupTable::dump() const {
151 for (const auto &Entry : LookupTable) {
152 DeclContext *DC = Entry.first;
153 StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
154 llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
155 dump(DC);
156 }
157 }
158
159 } // namespace clang
160