Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ASTDumper.cpp
35259 views
1
//===--- ASTDumper.cpp - Dumping implementation for ASTs ------------------===//
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 implements the AST dump methods, which dump out the
10
// AST in a form that exposes type details and other fields.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/AST/ASTDumper.h"
15
#include "clang/AST/ASTConcept.h"
16
#include "clang/AST/ASTContext.h"
17
#include "clang/AST/DeclLookups.h"
18
#include "clang/AST/JSONNodeDumper.h"
19
#include "clang/Basic/Builtins.h"
20
#include "clang/Basic/SourceManager.h"
21
#include "llvm/Support/raw_ostream.h"
22
23
using namespace clang;
24
using namespace clang::comments;
25
26
void ASTDumper::dumpInvalidDeclContext(const DeclContext *DC) {
27
NodeDumper.AddChild([=] {
28
if (!DC) {
29
ColorScope Color(OS, ShowColors, NullColor);
30
OS << "<<<NULL>>>";
31
return;
32
}
33
// An invalid DeclContext is one for which a dyn_cast() from a DeclContext
34
// pointer to a Decl pointer would fail an assertion or otherwise fall prey
35
// to undefined behavior as a result of an invalid associated DeclKind.
36
// Such invalidity is not supposed to happen of course, but, when it does,
37
// the information provided below is intended to provide some hints about
38
// what might have gone awry.
39
{
40
ColorScope Color(OS, ShowColors, DeclKindNameColor);
41
OS << "DeclContext";
42
}
43
NodeDumper.dumpPointer(DC);
44
OS << " <";
45
{
46
ColorScope Color(OS, ShowColors, DeclNameColor);
47
OS << "unrecognized Decl kind " << (unsigned)DC->getDeclKind();
48
}
49
OS << ">";
50
});
51
}
52
53
void ASTDumper::dumpLookups(const DeclContext *DC, bool DumpDecls) {
54
NodeDumper.AddChild([=] {
55
OS << "StoredDeclsMap ";
56
NodeDumper.dumpBareDeclRef(cast<Decl>(DC));
57
58
const DeclContext *Primary = DC->getPrimaryContext();
59
if (Primary != DC) {
60
OS << " primary";
61
NodeDumper.dumpPointer(cast<Decl>(Primary));
62
}
63
64
bool HasUndeserializedLookups = Primary->hasExternalVisibleStorage();
65
66
auto Range = getDeserialize()
67
? Primary->lookups()
68
: Primary->noload_lookups(/*PreserveInternalState=*/true);
69
for (auto I = Range.begin(), E = Range.end(); I != E; ++I) {
70
DeclarationName Name = I.getLookupName();
71
DeclContextLookupResult R = *I;
72
73
NodeDumper.AddChild([=] {
74
OS << "DeclarationName ";
75
{
76
ColorScope Color(OS, ShowColors, DeclNameColor);
77
OS << '\'' << Name << '\'';
78
}
79
80
for (DeclContextLookupResult::iterator RI = R.begin(), RE = R.end();
81
RI != RE; ++RI) {
82
NodeDumper.AddChild([=] {
83
NodeDumper.dumpBareDeclRef(*RI);
84
85
if (!(*RI)->isUnconditionallyVisible())
86
OS << " hidden";
87
88
// If requested, dump the redecl chain for this lookup.
89
if (DumpDecls) {
90
// Dump earliest decl first.
91
std::function<void(Decl *)> DumpWithPrev = [&](Decl *D) {
92
if (Decl *Prev = D->getPreviousDecl())
93
DumpWithPrev(Prev);
94
Visit(D);
95
};
96
DumpWithPrev(*RI);
97
}
98
});
99
}
100
});
101
}
102
103
if (HasUndeserializedLookups) {
104
NodeDumper.AddChild([=] {
105
ColorScope Color(OS, ShowColors, UndeserializedColor);
106
OS << "<undeserialized lookups>";
107
});
108
}
109
});
110
}
111
112
template <typename SpecializationDecl>
113
void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
114
bool DumpExplicitInst,
115
bool DumpRefOnly) {
116
bool DumpedAny = false;
117
for (const auto *RedeclWithBadType : D->redecls()) {
118
// FIXME: The redecls() range sometimes has elements of a less-specific
119
// type. (In particular, ClassTemplateSpecializationDecl::redecls() gives
120
// us TagDecls, and should give CXXRecordDecls).
121
auto *Redecl = cast<SpecializationDecl>(RedeclWithBadType);
122
switch (Redecl->getTemplateSpecializationKind()) {
123
case TSK_ExplicitInstantiationDeclaration:
124
case TSK_ExplicitInstantiationDefinition:
125
if (!DumpExplicitInst)
126
break;
127
[[fallthrough]];
128
case TSK_Undeclared:
129
case TSK_ImplicitInstantiation:
130
if (DumpRefOnly)
131
NodeDumper.dumpDeclRef(Redecl);
132
else
133
Visit(Redecl);
134
DumpedAny = true;
135
break;
136
case TSK_ExplicitSpecialization:
137
break;
138
}
139
}
140
141
// Ensure we dump at least one decl for each specialization.
142
if (!DumpedAny)
143
NodeDumper.dumpDeclRef(D);
144
}
145
146
template <typename TemplateDecl>
147
void ASTDumper::dumpTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst) {
148
dumpTemplateParameters(D->getTemplateParameters());
149
150
Visit(D->getTemplatedDecl());
151
152
if (GetTraversalKind() == TK_AsIs) {
153
for (const auto *Child : D->specializations())
154
dumpTemplateDeclSpecialization(Child, DumpExplicitInst,
155
!D->isCanonicalDecl());
156
}
157
}
158
159
void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
160
// FIXME: We don't add a declaration of a function template specialization
161
// to its context when it's explicitly instantiated, so dump explicit
162
// instantiations when we dump the template itself.
163
dumpTemplateDecl(D, true);
164
}
165
166
void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
167
dumpTemplateDecl(D, false);
168
}
169
170
void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
171
dumpTemplateDecl(D, false);
172
}
173
174
//===----------------------------------------------------------------------===//
175
// Type method implementations
176
//===----------------------------------------------------------------------===//
177
178
void QualType::dump(const char *msg) const {
179
if (msg)
180
llvm::errs() << msg << ": ";
181
dump();
182
}
183
184
LLVM_DUMP_METHOD void QualType::dump() const {
185
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
186
Dumper.Visit(*this);
187
}
188
189
LLVM_DUMP_METHOD void QualType::dump(llvm::raw_ostream &OS,
190
const ASTContext &Context) const {
191
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
192
Dumper.Visit(*this);
193
}
194
195
LLVM_DUMP_METHOD void Type::dump() const { QualType(this, 0).dump(); }
196
197
LLVM_DUMP_METHOD void Type::dump(llvm::raw_ostream &OS,
198
const ASTContext &Context) const {
199
QualType(this, 0).dump(OS, Context);
200
}
201
202
//===----------------------------------------------------------------------===//
203
// TypeLoc method implementations
204
//===----------------------------------------------------------------------===//
205
206
LLVM_DUMP_METHOD void TypeLoc::dump() const {
207
ASTDumper(llvm::errs(), /*ShowColors=*/false).Visit(*this);
208
}
209
210
LLVM_DUMP_METHOD void TypeLoc::dump(llvm::raw_ostream &OS,
211
const ASTContext &Context) const {
212
ASTDumper(OS, Context, Context.getDiagnostics().getShowColors()).Visit(*this);
213
}
214
215
//===----------------------------------------------------------------------===//
216
// Decl method implementations
217
//===----------------------------------------------------------------------===//
218
219
LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); }
220
221
LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS, bool Deserialize,
222
ASTDumpOutputFormat Format) const {
223
ASTContext &Ctx = getASTContext();
224
const SourceManager &SM = Ctx.getSourceManager();
225
226
if (ADOF_JSON == Format) {
227
JSONDumper P(OS, SM, Ctx, Ctx.getPrintingPolicy(),
228
&Ctx.getCommentCommandTraits());
229
(void)Deserialize; // FIXME?
230
P.Visit(this);
231
} else {
232
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
233
P.setDeserialize(Deserialize);
234
P.Visit(this);
235
}
236
}
237
238
LLVM_DUMP_METHOD void Decl::dumpColor() const {
239
const ASTContext &Ctx = getASTContext();
240
ASTDumper P(llvm::errs(), Ctx, /*ShowColors=*/true);
241
P.Visit(this);
242
}
243
244
LLVM_DUMP_METHOD void DeclContext::dumpAsDecl() const {
245
dumpAsDecl(nullptr);
246
}
247
248
LLVM_DUMP_METHOD void DeclContext::dumpAsDecl(const ASTContext *Ctx) const {
249
// By design, DeclContext is required to be a base class of some class that
250
// derives from Decl. Thus, it should always be possible to dyn_cast() from
251
// a DeclContext pointer to a Decl pointer and Decl::castFromDeclContext()
252
// asserts that to be the case. Since this function is intended for use in a
253
// debugger, it performs an additional check in order to prevent a failed
254
// cast and assertion. If that check fails, then the (invalid) DeclContext
255
// is dumped with an indication of its invalidity.
256
if (hasValidDeclKind()) {
257
const auto *D = cast<Decl>(this);
258
D->dump();
259
} else {
260
// If an ASTContext is not available, a less capable ASTDumper is
261
// constructed for which color diagnostics are, regrettably, disabled.
262
ASTDumper P = Ctx ? ASTDumper(llvm::errs(), *Ctx,
263
Ctx->getDiagnostics().getShowColors())
264
: ASTDumper(llvm::errs(), /*ShowColors*/ false);
265
P.dumpInvalidDeclContext(this);
266
}
267
}
268
269
LLVM_DUMP_METHOD void DeclContext::dumpLookups() const {
270
dumpLookups(llvm::errs());
271
}
272
273
LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS,
274
bool DumpDecls,
275
bool Deserialize) const {
276
const DeclContext *DC = this;
277
while (!DC->isTranslationUnit())
278
DC = DC->getParent();
279
const ASTContext &Ctx = cast<TranslationUnitDecl>(DC)->getASTContext();
280
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
281
P.setDeserialize(Deserialize);
282
P.dumpLookups(this, DumpDecls);
283
}
284
285
//===----------------------------------------------------------------------===//
286
// Stmt method implementations
287
//===----------------------------------------------------------------------===//
288
289
LLVM_DUMP_METHOD void Stmt::dump() const {
290
ASTDumper P(llvm::errs(), /*ShowColors=*/false);
291
P.Visit(this);
292
}
293
294
LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS,
295
const ASTContext &Context) const {
296
ASTDumper P(OS, Context, Context.getDiagnostics().getShowColors());
297
P.Visit(this);
298
}
299
300
LLVM_DUMP_METHOD void Stmt::dumpColor() const {
301
ASTDumper P(llvm::errs(), /*ShowColors=*/true);
302
P.Visit(this);
303
}
304
305
//===----------------------------------------------------------------------===//
306
// Comment method implementations
307
//===----------------------------------------------------------------------===//
308
309
LLVM_DUMP_METHOD void Comment::dump() const {
310
const auto *FC = dyn_cast<FullComment>(this);
311
if (!FC)
312
return;
313
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
314
Dumper.Visit(FC, FC);
315
}
316
317
LLVM_DUMP_METHOD void Comment::dump(raw_ostream &OS,
318
const ASTContext &Context) const {
319
const auto *FC = dyn_cast<FullComment>(this);
320
if (!FC)
321
return;
322
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
323
Dumper.Visit(FC, FC);
324
}
325
326
LLVM_DUMP_METHOD void Comment::dumpColor() const {
327
const auto *FC = dyn_cast<FullComment>(this);
328
if (!FC)
329
return;
330
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/true);
331
Dumper.Visit(FC, FC);
332
}
333
334
//===----------------------------------------------------------------------===//
335
// APValue method implementations
336
//===----------------------------------------------------------------------===//
337
338
LLVM_DUMP_METHOD void APValue::dump() const {
339
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
340
Dumper.Visit(*this, /*Ty=*/QualType());
341
}
342
343
LLVM_DUMP_METHOD void APValue::dump(raw_ostream &OS,
344
const ASTContext &Context) const {
345
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
346
Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
347
}
348
349
//===----------------------------------------------------------------------===//
350
// ConceptReference method implementations
351
//===----------------------------------------------------------------------===//
352
353
LLVM_DUMP_METHOD void ConceptReference::dump() const {
354
dump(llvm::errs());
355
}
356
357
LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {
358
auto &Ctx = getNamedConcept()->getASTContext();
359
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
360
P.Visit(this);
361
}
362
363
//===----------------------------------------------------------------------===//
364
// TemplateName method implementations
365
//===----------------------------------------------------------------------===//
366
367
// FIXME: These are actually using the TemplateArgument dumper, through
368
// an implicit conversion. The dump will claim this is a template argument,
369
// which is misleading.
370
371
LLVM_DUMP_METHOD void TemplateName::dump() const {
372
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
373
Dumper.Visit(*this);
374
}
375
376
LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,
377
const ASTContext &Context) const {
378
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
379
Dumper.Visit(*this);
380
}
381
382
//===----------------------------------------------------------------------===//
383
// TemplateArgument method implementations
384
//===----------------------------------------------------------------------===//
385
386
LLVM_DUMP_METHOD void TemplateArgument::dump() const {
387
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
388
Dumper.Visit(*this);
389
}
390
391
LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,
392
const ASTContext &Context) const {
393
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
394
Dumper.Visit(*this);
395
}
396
397