Coverage Report

Created: 2024-01-17 10:31

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