Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ASTImporterLookupTable.cpp
35260 views
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
#include "llvm/Support/FormatVariadic.h"
18
19
namespace clang {
20
21
namespace {
22
23
struct Builder : RecursiveASTVisitor<Builder> {
24
ASTImporterLookupTable &LT;
25
Builder(ASTImporterLookupTable &LT) : LT(LT) {}
26
27
bool VisitTypedefNameDecl(TypedefNameDecl *D) {
28
QualType Ty = D->getUnderlyingType();
29
Ty = Ty.getCanonicalType();
30
if (const auto *RTy = dyn_cast<RecordType>(Ty)) {
31
LT.add(RTy->getAsRecordDecl());
32
// iterate over the field decls, adding them
33
for (auto *it : RTy->getAsRecordDecl()->fields()) {
34
LT.add(it);
35
}
36
}
37
return true;
38
}
39
40
bool VisitNamedDecl(NamedDecl *D) {
41
LT.add(D);
42
return true;
43
}
44
// In most cases the FriendDecl contains the declaration of the befriended
45
// class as a child node, so it is discovered during the recursive
46
// visitation. However, there are cases when the befriended class is not a
47
// child, thus it must be fetched explicitly from the FriendDecl, and only
48
// then can we add it to the lookup table.
49
bool VisitFriendDecl(FriendDecl *D) {
50
if (D->getFriendType()) {
51
QualType Ty = D->getFriendType()->getType();
52
if (isa<ElaboratedType>(Ty))
53
Ty = cast<ElaboratedType>(Ty)->getNamedType();
54
// A FriendDecl with a dependent type (e.g. ClassTemplateSpecialization)
55
// always has that decl as child node.
56
// However, there are non-dependent cases which does not have the
57
// type as a child node. We have to dig up that type now.
58
if (!Ty->isDependentType()) {
59
if (const auto *RTy = dyn_cast<RecordType>(Ty))
60
LT.add(RTy->getAsCXXRecordDecl());
61
else if (const auto *SpecTy = dyn_cast<TemplateSpecializationType>(Ty))
62
LT.add(SpecTy->getAsCXXRecordDecl());
63
else if (const auto *SubstTy =
64
dyn_cast<SubstTemplateTypeParmType>(Ty)) {
65
if (SubstTy->getAsCXXRecordDecl())
66
LT.add(SubstTy->getAsCXXRecordDecl());
67
} else if (isa<TypedefType>(Ty)) {
68
// We do not put friend typedefs to the lookup table because
69
// ASTImporter does not organize typedefs into redecl chains.
70
} else if (isa<UsingType>(Ty)) {
71
// Similar to TypedefType, not putting into lookup table.
72
} else {
73
llvm_unreachable("Unhandled type of friend class");
74
}
75
}
76
}
77
return true;
78
}
79
80
// Override default settings of base.
81
bool shouldVisitTemplateInstantiations() const { return true; }
82
bool shouldVisitImplicitCode() const { return true; }
83
};
84
85
} // anonymous namespace
86
87
ASTImporterLookupTable::ASTImporterLookupTable(TranslationUnitDecl &TU) {
88
Builder B(*this);
89
B.TraverseDecl(&TU);
90
// The VaList declaration may be created on demand only or not traversed.
91
// To ensure it is present and found during import, add it to the table now.
92
if (auto *D =
93
dyn_cast_or_null<NamedDecl>(TU.getASTContext().getVaListTagDecl())) {
94
// On some platforms (AArch64) the VaList declaration can be inside a 'std'
95
// namespace. This is handled specially and not visible by AST traversal.
96
// ASTImporter must be able to find this namespace to import the VaList
97
// declaration (and the namespace) correctly.
98
if (auto *Ns = dyn_cast<NamespaceDecl>(D->getDeclContext()))
99
add(&TU, Ns);
100
add(D->getDeclContext(), D);
101
}
102
}
103
104
void ASTImporterLookupTable::add(DeclContext *DC, NamedDecl *ND) {
105
DeclList &Decls = LookupTable[DC][ND->getDeclName()];
106
// Inserts if and only if there is no element in the container equal to it.
107
Decls.insert(ND);
108
}
109
110
void ASTImporterLookupTable::remove(DeclContext *DC, NamedDecl *ND) {
111
const DeclarationName Name = ND->getDeclName();
112
DeclList &Decls = LookupTable[DC][Name];
113
bool EraseResult = Decls.remove(ND);
114
(void)EraseResult;
115
#ifndef NDEBUG
116
if (!EraseResult) {
117
std::string Message =
118
llvm::formatv("Trying to remove not contained Decl '{0}' of type {1}",
119
Name.getAsString(), DC->getDeclKindName())
120
.str();
121
llvm_unreachable(Message.c_str());
122
}
123
#endif
124
}
125
126
void ASTImporterLookupTable::add(NamedDecl *ND) {
127
assert(ND);
128
DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
129
add(DC, ND);
130
DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
131
if (DC != ReDC)
132
add(ReDC, ND);
133
}
134
135
void ASTImporterLookupTable::remove(NamedDecl *ND) {
136
assert(ND);
137
DeclContext *DC = ND->getDeclContext()->getPrimaryContext();
138
remove(DC, ND);
139
DeclContext *ReDC = DC->getRedeclContext()->getPrimaryContext();
140
if (DC != ReDC)
141
remove(ReDC, ND);
142
}
143
144
void ASTImporterLookupTable::update(NamedDecl *ND, DeclContext *OldDC) {
145
assert(OldDC != ND->getDeclContext() &&
146
"DeclContext should be changed before update");
147
if (contains(ND->getDeclContext(), ND)) {
148
assert(!contains(OldDC, ND) &&
149
"Decl should not be found in the old context if already in the new");
150
return;
151
}
152
153
remove(OldDC, ND);
154
add(ND);
155
}
156
157
void ASTImporterLookupTable::updateForced(NamedDecl *ND, DeclContext *OldDC) {
158
LookupTable[OldDC][ND->getDeclName()].remove(ND);
159
add(ND);
160
}
161
162
ASTImporterLookupTable::LookupResult
163
ASTImporterLookupTable::lookup(DeclContext *DC, DeclarationName Name) const {
164
auto DCI = LookupTable.find(DC->getPrimaryContext());
165
if (DCI == LookupTable.end())
166
return {};
167
168
const auto &FoundNameMap = DCI->second;
169
auto NamesI = FoundNameMap.find(Name);
170
if (NamesI == FoundNameMap.end())
171
return {};
172
173
return NamesI->second;
174
}
175
176
bool ASTImporterLookupTable::contains(DeclContext *DC, NamedDecl *ND) const {
177
return lookup(DC, ND->getDeclName()).contains(ND);
178
}
179
180
void ASTImporterLookupTable::dump(DeclContext *DC) const {
181
auto DCI = LookupTable.find(DC->getPrimaryContext());
182
if (DCI == LookupTable.end())
183
llvm::errs() << "empty\n";
184
const auto &FoundNameMap = DCI->second;
185
for (const auto &Entry : FoundNameMap) {
186
DeclarationName Name = Entry.first;
187
llvm::errs() << "==== Name: ";
188
Name.dump();
189
const DeclList& List = Entry.second;
190
for (NamedDecl *ND : List) {
191
ND->dump();
192
}
193
}
194
}
195
196
void ASTImporterLookupTable::dump() const {
197
for (const auto &Entry : LookupTable) {
198
DeclContext *DC = Entry.first;
199
StringRef Primary = DC->getPrimaryContext() ? " primary" : "";
200
llvm::errs() << "== DC:" << cast<Decl>(DC) << Primary << "\n";
201
dump(DC);
202
}
203
}
204
205
} // namespace clang
206
207